mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge from innodb-branches-innodb+ (2)
This commit is contained in:
@@ -952,6 +952,7 @@ btr_page_reorganize_low(
|
||||
dict_index_t* index, /*!< in: record descriptor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(&block->page);
|
||||
page_t* page = buf_block_get_frame(block);
|
||||
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
|
||||
buf_block_t* temp_block;
|
||||
@@ -982,7 +983,7 @@ btr_page_reorganize_low(
|
||||
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
temp_block = buf_block_alloc(0);
|
||||
temp_block = buf_block_alloc(buf_pool, 0);
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
ut_ad(block == back_block1);
|
||||
temp_block = back_block2;
|
||||
|
@@ -3882,14 +3882,15 @@ btr_blob_free(
|
||||
if there is one */
|
||||
mtr_t* mtr) /*!< in: mini-transaction to commit */
|
||||
{
|
||||
ulint space = buf_block_get_space(block);
|
||||
ulint page_no = buf_block_get_page_no(block);
|
||||
buf_pool_t* buf_pool = buf_pool_from_block(block);
|
||||
ulint space = buf_block_get_space(block);
|
||||
ulint page_no = buf_block_get_page_no(block);
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
mtr_commit(mtr);
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
/* Only free the block if it is still allocated to
|
||||
@@ -3910,7 +3911,7 @@ btr_blob_free(
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
mutex_exit(&block->mutex);
|
||||
}
|
||||
|
||||
|
@@ -150,7 +150,7 @@ btr_search_check_free_space_in_heap(void)
|
||||
be enough free space in the hash table. */
|
||||
|
||||
if (heap->free_block == NULL) {
|
||||
buf_block_t* block = buf_block_alloc(0);
|
||||
buf_block_t* block = buf_block_alloc(NULL, 0);
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
|
||||
@@ -825,6 +825,7 @@ btr_search_guess_on_hash(
|
||||
RW_S_LATCH, RW_X_LATCH, or 0 */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
buf_pool_t* buf_pool;
|
||||
buf_block_t* block;
|
||||
rec_t* rec;
|
||||
ulint fold;
|
||||
@@ -983,7 +984,7 @@ btr_search_guess_on_hash(
|
||||
|
||||
/* Increment the page get statistics though we did not really
|
||||
fix the page: for user info only */
|
||||
|
||||
buf_pool = buf_pool_from_bpage(&block->page);
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
||||
return(TRUE);
|
||||
@@ -1760,7 +1761,7 @@ btr_search_validate(void)
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_mutex_enter_all();
|
||||
|
||||
cell_count = hash_get_n_cells(btr_search_sys->hash_index);
|
||||
|
||||
@@ -1768,11 +1769,11 @@ btr_search_validate(void)
|
||||
/* We release btr_search_latch every once in a while to
|
||||
give other queries a chance to run. */
|
||||
if ((i != 0) && ((i % chunk_size) == 0)) {
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit_all();
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
os_thread_yield();
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_mutex_enter_all();
|
||||
}
|
||||
|
||||
node = hash_get_nth_cell(btr_search_sys->hash_index, i)->node;
|
||||
@@ -1781,6 +1782,9 @@ btr_search_validate(void)
|
||||
const buf_block_t* block
|
||||
= buf_block_align(node->data);
|
||||
const buf_block_t* hash_block;
|
||||
buf_pool_t* buf_pool;
|
||||
|
||||
buf_pool = buf_pool_from_bpage((buf_page_t*) block);
|
||||
|
||||
if (UNIV_LIKELY(buf_block_get_state(block)
|
||||
== BUF_BLOCK_FILE_PAGE)) {
|
||||
@@ -1791,6 +1795,7 @@ btr_search_validate(void)
|
||||
(BUF_BLOCK_REMOVE_HASH, see the
|
||||
assertion and the comment below) */
|
||||
hash_block = buf_block_hash_get(
|
||||
buf_pool,
|
||||
buf_block_get_space(block),
|
||||
buf_block_get_page_no(block));
|
||||
} else {
|
||||
@@ -1879,11 +1884,11 @@ btr_search_validate(void)
|
||||
/* We release btr_search_latch every once in a while to
|
||||
give other queries a chance to run. */
|
||||
if (i != 0) {
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit_all();
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
os_thread_yield();
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_mutex_enter_all();
|
||||
}
|
||||
|
||||
if (!ha_validate(btr_search_sys->hash_index, i, end_index)) {
|
||||
@@ -1891,7 +1896,7 @@ btr_search_validate(void)
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit_all();
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
|
@@ -34,17 +34,6 @@ Created December 2006 by Marko Makela
|
||||
#include "buf0flu.h"
|
||||
#include "page0zip.h"
|
||||
|
||||
/* Statistic counters */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Number of frames allocated from the buffer pool to the buddy system.
|
||||
Protected by buf_pool_mutex. */
|
||||
static ulint buf_buddy_n_frames;
|
||||
#endif /* UNIV_DEBUG */
|
||||
/** Statistics of the buddy system, indexed by block size.
|
||||
Protected by buf_pool_mutex. */
|
||||
UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
|
||||
|
||||
/**********************************************************************//**
|
||||
Get the offset of the buddy of a compressed page frame.
|
||||
@return the buddy relative of page */
|
||||
@@ -73,8 +62,10 @@ UNIV_INLINE
|
||||
void
|
||||
buf_buddy_add_to_free(
|
||||
/*==================*/
|
||||
buf_page_t* bpage, /*!< in,own: block to be freed */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[] */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
buf_page_t* bpage, /*!< in,own: block to be freed */
|
||||
ulint i) /*!< in: index of
|
||||
buf_pool->zip_free[] */
|
||||
{
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
buf_page_t* b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
|
||||
@@ -82,7 +73,7 @@ buf_buddy_add_to_free(
|
||||
if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
|
||||
ut_ad(buf_pool->zip_free[i].start != bpage);
|
||||
UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
|
||||
@@ -99,8 +90,10 @@ UNIV_INLINE
|
||||
void
|
||||
buf_buddy_remove_from_free(
|
||||
/*=======================*/
|
||||
buf_page_t* bpage, /*!< in: block to be removed */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[] */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
buf_page_t* bpage, /*!< in: block to be removed */
|
||||
ulint i) /*!< in: index of
|
||||
buf_pool->zip_free[] */
|
||||
{
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
buf_page_t* prev = UT_LIST_GET_PREV(list, bpage);
|
||||
@@ -113,7 +106,7 @@ buf_buddy_remove_from_free(
|
||||
ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
|
||||
UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
|
||||
|
||||
@@ -130,11 +123,12 @@ static
|
||||
void*
|
||||
buf_buddy_alloc_zip(
|
||||
/*================*/
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[] */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[] */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_a(i < BUF_BUDDY_SIZES);
|
||||
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
@@ -149,19 +143,19 @@ buf_buddy_alloc_zip(
|
||||
UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
|
||||
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
|
||||
|
||||
buf_buddy_remove_from_free(bpage, i);
|
||||
buf_buddy_remove_from_free(buf_pool, bpage, i);
|
||||
} else if (i + 1 < BUF_BUDDY_SIZES) {
|
||||
/* Attempt to split. */
|
||||
bpage = buf_buddy_alloc_zip(i + 1);
|
||||
bpage = buf_buddy_alloc_zip(buf_pool, i + 1);
|
||||
|
||||
if (bpage) {
|
||||
buf_page_t* buddy = (buf_page_t*)
|
||||
(((char*) bpage) + (BUF_BUDDY_LOW << i));
|
||||
|
||||
ut_ad(!buf_pool_contains_zip(buddy));
|
||||
ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
|
||||
ut_d(memset(buddy, i, BUF_BUDDY_LOW << i));
|
||||
buddy->state = BUF_BLOCK_ZIP_FREE;
|
||||
buf_buddy_add_to_free(buddy, i);
|
||||
buf_buddy_add_to_free(buf_pool, buddy, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,14 +176,15 @@ static
|
||||
void
|
||||
buf_buddy_block_free(
|
||||
/*=================*/
|
||||
void* buf) /*!< in: buffer frame to deallocate */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
void* buf) /*!< in: buffer frame to deallocate */
|
||||
{
|
||||
const ulint fold = BUF_POOL_ZIP_FOLD_PTR(buf);
|
||||
buf_page_t* bpage;
|
||||
buf_block_t* block;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
|
||||
|
||||
HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
|
||||
@@ -211,8 +206,8 @@ buf_buddy_block_free(
|
||||
buf_LRU_block_free_non_file_page(block);
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
ut_ad(buf_buddy_n_frames > 0);
|
||||
ut_d(buf_buddy_n_frames--);
|
||||
ut_ad(buf_pool->buddy_n_frames > 0);
|
||||
ut_d(buf_pool->buddy_n_frames--);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
@@ -223,9 +218,10 @@ buf_buddy_block_register(
|
||||
/*=====================*/
|
||||
buf_block_t* block) /*!< in: buffer frame to allocate */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_block(block);
|
||||
const ulint fold = BUF_POOL_ZIP_FOLD(block);
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
|
||||
|
||||
buf_block_set_state(block, BUF_BLOCK_MEMORY);
|
||||
@@ -238,7 +234,7 @@ buf_buddy_block_register(
|
||||
ut_d(block->page.in_zip_hash = TRUE);
|
||||
HASH_INSERT(buf_page_t, hash, buf_pool->zip_hash, fold, &block->page);
|
||||
|
||||
ut_d(buf_buddy_n_frames++);
|
||||
ut_d(buf_pool->buddy_n_frames++);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
@@ -248,10 +244,12 @@ static
|
||||
void*
|
||||
buf_buddy_alloc_from(
|
||||
/*=================*/
|
||||
void* buf, /*!< in: a block that is free to use */
|
||||
ulint i, /*!< in: index of buf_pool->zip_free[] */
|
||||
ulint j) /*!< in: size of buf as an index
|
||||
of buf_pool->zip_free[] */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
void* buf, /*!< in: a block that is free to use */
|
||||
ulint i, /*!< in: index of
|
||||
buf_pool->zip_free[] */
|
||||
ulint j) /*!< in: size of buf as an index
|
||||
of buf_pool->zip_free[] */
|
||||
{
|
||||
ulint offs = BUF_BUDDY_LOW << j;
|
||||
ut_ad(j <= BUF_BUDDY_SIZES);
|
||||
@@ -275,7 +273,7 @@ buf_buddy_alloc_from(
|
||||
ut_list_node_313)
|
||||
== BUF_BLOCK_ZIP_FREE)));
|
||||
#endif /* !UNIV_DEBUG_VALGRIND */
|
||||
buf_buddy_add_to_free(bpage, j);
|
||||
buf_buddy_add_to_free(buf_pool, bpage, j);
|
||||
}
|
||||
|
||||
return(buf);
|
||||
@@ -283,37 +281,39 @@ buf_buddy_alloc_from(
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool_mutex and must not hold buf_pool_zip_mutex or any block->mutex.
|
||||
The buf_pool_mutex may only be released and reacquired if lru != NULL.
|
||||
buf_pool->mutex and must not hold buf_pool_zip_mutex or any block->mutex.
|
||||
The buf_pool->mutex may only be released and reacquired if lru != NULL.
|
||||
@return allocated block, possibly NULL if lru==NULL */
|
||||
UNIV_INTERN
|
||||
void*
|
||||
buf_buddy_alloc_low(
|
||||
/*================*/
|
||||
ulint i, /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
ibool* lru) /*!< in: pointer to a variable that will be assigned
|
||||
TRUE if storage was allocated from the LRU list
|
||||
and buf_pool_mutex was temporarily released,
|
||||
or NULL if the LRU list should not be used */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint i, /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
ibool* lru) /*!< in: pointer to a variable that
|
||||
will be assigned TRUE if storage was
|
||||
allocated from the LRU list and
|
||||
buf_pool->mutex was temporarily
|
||||
released, or NULL if the LRU list
|
||||
should not be used */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
|
||||
if (i < BUF_BUDDY_SIZES) {
|
||||
/* Try to allocate from the buddy system. */
|
||||
block = buf_buddy_alloc_zip(i);
|
||||
block = buf_buddy_alloc_zip(buf_pool, i);
|
||||
|
||||
if (block) {
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try allocating from the buf_pool->free list. */
|
||||
block = buf_LRU_get_free_only();
|
||||
block = buf_LRU_get_free_only(buf_pool);
|
||||
|
||||
if (block) {
|
||||
|
||||
@@ -326,18 +326,19 @@ buf_buddy_alloc_low(
|
||||
}
|
||||
|
||||
/* Try replacing an uncompressed page in the buffer pool. */
|
||||
buf_pool_mutex_exit();
|
||||
block = buf_LRU_get_free_block(0);
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
block = buf_LRU_get_free_block(buf_pool, 0);
|
||||
*lru = TRUE;
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
alloc_big:
|
||||
buf_buddy_block_register(block);
|
||||
|
||||
block = buf_buddy_alloc_from(block->frame, i, BUF_BUDDY_SIZES);
|
||||
block = buf_buddy_alloc_from(
|
||||
buf_pool, block->frame, i, BUF_BUDDY_SIZES);
|
||||
|
||||
func_exit:
|
||||
buf_buddy_stat[i].used++;
|
||||
buf_pool->buddy_stat[i].used++;
|
||||
return(block);
|
||||
}
|
||||
|
||||
@@ -352,8 +353,9 @@ buf_buddy_relocate_block(
|
||||
buf_page_t* dpage) /*!< in: free block to relocate to */
|
||||
{
|
||||
buf_page_t* b;
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
|
||||
switch (buf_page_get_state(bpage)) {
|
||||
case BUF_BLOCK_ZIP_FREE:
|
||||
@@ -371,10 +373,10 @@ buf_buddy_relocate_block(
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_enter(&buf_pool_zip_mutex);
|
||||
mutex_enter(&buf_pool->zip_mutex);
|
||||
|
||||
if (!buf_page_can_relocate(bpage)) {
|
||||
mutex_exit(&buf_pool_zip_mutex);
|
||||
mutex_exit(&buf_pool->zip_mutex);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
@@ -393,7 +395,7 @@ buf_buddy_relocate_block(
|
||||
|
||||
UNIV_MEM_INVALID(bpage, sizeof *bpage);
|
||||
|
||||
mutex_exit(&buf_pool_zip_mutex);
|
||||
mutex_exit(&buf_pool->zip_mutex);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
@@ -404,16 +406,18 @@ static
|
||||
ibool
|
||||
buf_buddy_relocate(
|
||||
/*===============*/
|
||||
void* src, /*!< in: block to relocate */
|
||||
void* dst, /*!< in: free block to relocate to */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[] */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
void* src, /*!< in: block to relocate */
|
||||
void* dst, /*!< in: free block to relocate to */
|
||||
ulint i) /*!< in: index of
|
||||
buf_pool->zip_free[] */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
const ulint size = BUF_BUDDY_LOW << i;
|
||||
ullint usec = ut_time_us(NULL);
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
ut_ad(!ut_align_offset(src, size));
|
||||
ut_ad(!ut_align_offset(dst, size));
|
||||
UNIV_MEM_ASSERT_W(dst, size);
|
||||
@@ -443,6 +447,7 @@ buf_buddy_relocate(
|
||||
mach_read_from_4() calls here will only trigger bogus
|
||||
Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
|
||||
bpage = buf_page_hash_get(
|
||||
buf_pool,
|
||||
mach_read_from_4((const byte*) src
|
||||
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID),
|
||||
mach_read_from_4((const byte*) src
|
||||
@@ -457,7 +462,7 @@ buf_buddy_relocate(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
ut_ad(!buf_pool_watch_is(bpage));
|
||||
ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
|
||||
|
||||
if (page_zip_get_size(&bpage->zip) != size) {
|
||||
/* The block is of different size. We would
|
||||
@@ -486,7 +491,7 @@ success:
|
||||
UNIV_MEM_INVALID(src, size);
|
||||
{
|
||||
buf_buddy_stat_t* buddy_stat
|
||||
= &buf_buddy_stat[i];
|
||||
= &buf_pool->buddy_stat[i];
|
||||
buddy_stat->relocated++;
|
||||
buddy_stat->relocated_usec
|
||||
+= ut_time_us(NULL) - usec;
|
||||
@@ -513,32 +518,33 @@ UNIV_INTERN
|
||||
void
|
||||
buf_buddy_free_low(
|
||||
/*===============*/
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
buf_page_t* buddy;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!mutex_own(&buf_pool->zip_mutex));
|
||||
ut_ad(i <= BUF_BUDDY_SIZES);
|
||||
ut_ad(buf_buddy_stat[i].used > 0);
|
||||
ut_ad(buf_pool->buddy_stat[i].used > 0);
|
||||
|
||||
buf_buddy_stat[i].used--;
|
||||
buf_pool->buddy_stat[i].used--;
|
||||
recombine:
|
||||
UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
|
||||
ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
|
||||
|
||||
if (i == BUF_BUDDY_SIZES) {
|
||||
buf_buddy_block_free(buf);
|
||||
buf_buddy_block_free(buf_pool, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(i < BUF_BUDDY_SIZES);
|
||||
ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
|
||||
ut_ad(!buf_pool_contains_zip(buf));
|
||||
ut_ad(!buf_pool_contains_zip(buf_pool, buf));
|
||||
|
||||
/* Try to combine adjacent blocks. */
|
||||
|
||||
@@ -564,10 +570,10 @@ recombine:
|
||||
if (bpage == buddy) {
|
||||
buddy_free:
|
||||
/* The buddy is free: recombine */
|
||||
buf_buddy_remove_from_free(bpage, i);
|
||||
buf_buddy_remove_from_free(buf_pool, bpage, i);
|
||||
buddy_free2:
|
||||
ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
|
||||
ut_ad(!buf_pool_contains_zip(buddy));
|
||||
ut_ad(!buf_pool_contains_zip(buf_pool, buddy));
|
||||
i++;
|
||||
buf = ut_align_down(buf, BUF_BUDDY_LOW << i);
|
||||
|
||||
@@ -599,16 +605,16 @@ buddy_nonfree:
|
||||
buf_buddy_relocate() will overwrite bpage->list. */
|
||||
|
||||
UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
|
||||
buf_buddy_remove_from_free(bpage, i);
|
||||
buf_buddy_remove_from_free(buf_pool, bpage, i);
|
||||
|
||||
/* Try to relocate the buddy of buf to the free block. */
|
||||
if (buf_buddy_relocate(buddy, bpage, i)) {
|
||||
if (buf_buddy_relocate(buf_pool, buddy, bpage, i)) {
|
||||
|
||||
ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
|
||||
goto buddy_free2;
|
||||
}
|
||||
|
||||
buf_buddy_add_to_free(bpage, i);
|
||||
buf_buddy_add_to_free(buf_pool, bpage, i);
|
||||
|
||||
/* Try to relocate the buddy of the free block to buf. */
|
||||
buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
|
||||
@@ -629,7 +635,7 @@ buddy_nonfree:
|
||||
&& ut_list_node_313 != buddy)));
|
||||
#endif /* !UNIV_DEBUG_VALGRIND */
|
||||
|
||||
if (buf_buddy_relocate(buddy, buf, i)) {
|
||||
if (buf_buddy_relocate(buf_pool, buddy, buf, i)) {
|
||||
|
||||
buf = bpage;
|
||||
UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
|
||||
@@ -692,5 +698,5 @@ buddy_nonfree:
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
bpage->state = BUF_BLOCK_ZIP_FREE;
|
||||
buf_buddy_add_to_free(bpage, i);
|
||||
buf_buddy_add_to_free(buf_pool, bpage, i);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -171,6 +171,7 @@ buf_read_page(
|
||||
ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
|
||||
ulint offset) /*!< in: page number */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, offset);
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
ulint err;
|
||||
@@ -195,7 +196,7 @@ buf_read_page(
|
||||
}
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
buf_flush_free_margin(buf_pool);
|
||||
|
||||
/* Increment number of I/O operations used for LRU policy. */
|
||||
buf_LRU_stat_inc_io();
|
||||
@@ -236,6 +237,7 @@ buf_read_ahead_linear(
|
||||
ulint offset) /*!< in: page number of a page; NOTE: the current thread
|
||||
must want access to this page (see NOTE 3 above) */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, offset);
|
||||
ib_int64_t tablespace_version;
|
||||
buf_page_t* bpage;
|
||||
buf_frame_t* frame;
|
||||
@@ -251,7 +253,7 @@ buf_read_ahead_linear(
|
||||
ulint err;
|
||||
ulint i;
|
||||
const ulint buf_read_ahead_linear_area
|
||||
= BUF_READ_AHEAD_LINEAR_AREA;
|
||||
= BUF_READ_AHEAD_LINEAR_AREA(buf_pool);
|
||||
ulint threshold;
|
||||
|
||||
if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
|
||||
@@ -286,10 +288,10 @@ buf_read_ahead_linear(
|
||||
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
if (high > fil_space_get_size(space)) {
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
/* The area is not whole, return */
|
||||
|
||||
return(0);
|
||||
@@ -297,7 +299,7 @@ buf_read_ahead_linear(
|
||||
|
||||
if (buf_pool->n_pend_reads
|
||||
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -315,14 +317,14 @@ buf_read_ahead_linear(
|
||||
/* How many out of order accessed pages can we ignore
|
||||
when working out the access pattern for linear readahead */
|
||||
threshold = ut_min((64 - srv_read_ahead_threshold),
|
||||
BUF_READ_AHEAD_AREA);
|
||||
BUF_READ_AHEAD_AREA(buf_pool));
|
||||
|
||||
fail_count = 0;
|
||||
|
||||
for (i = low; i < high; i++) {
|
||||
bpage = buf_page_hash_get(space, i);
|
||||
bpage = buf_page_hash_get(buf_pool, space, i);
|
||||
|
||||
if ((bpage == NULL) || !buf_page_is_accessed(bpage)) {
|
||||
if (bpage == NULL || !buf_page_is_accessed(bpage)) {
|
||||
/* Not accessed */
|
||||
fail_count++;
|
||||
|
||||
@@ -346,7 +348,7 @@ buf_read_ahead_linear(
|
||||
|
||||
if (fail_count > threshold) {
|
||||
/* Too many failures: return */
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -358,10 +360,10 @@ buf_read_ahead_linear(
|
||||
/* If we got this far, we know that enough pages in the area have
|
||||
been accessed in the right order: linear read-ahead can be sensible */
|
||||
|
||||
bpage = buf_page_hash_get(space, offset);
|
||||
bpage = buf_page_hash_get(buf_pool, space, offset);
|
||||
|
||||
if (bpage == NULL) {
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -387,7 +389,7 @@ buf_read_ahead_linear(
|
||||
pred_offset = fil_page_get_prev(frame);
|
||||
succ_offset = fil_page_get_next(frame);
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
if ((offset == low) && (succ_offset == offset + 1)) {
|
||||
|
||||
@@ -466,7 +468,7 @@ buf_read_ahead_linear(
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
buf_flush_free_margin(buf_pool);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints && (count > 0)) {
|
||||
@@ -518,14 +520,18 @@ buf_read_ibuf_merge_pages(
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
ut_a(n_stored < UNIV_PAGE_SIZE);
|
||||
#endif
|
||||
while (buf_pool->n_pend_reads
|
||||
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
|
||||
os_thread_sleep(500000);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_stored; i++) {
|
||||
ulint zip_size = fil_space_get_zip_size(space_ids[i]);
|
||||
ulint err;
|
||||
ulint err;
|
||||
buf_pool_t* buf_pool;
|
||||
ulint zip_size = fil_space_get_zip_size(space_ids[i]);
|
||||
|
||||
buf_pool = buf_pool_get(space_ids[i], space_versions[i]);
|
||||
|
||||
while (buf_pool->n_pend_reads
|
||||
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
|
||||
os_thread_sleep(500000);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
|
||||
|
||||
@@ -550,8 +556,8 @@ tablespace_deleted:
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
/* Flush pages from the end of all the LRU lists if necessary */
|
||||
buf_flush_free_margins();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
@@ -600,11 +606,12 @@ buf_read_recv_pages(
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
for (i = 0; i < n_stored; i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
|
||||
count = 0;
|
||||
|
||||
os_aio_print_debug = FALSE;
|
||||
|
||||
buf_pool = buf_pool_get(space, page_nos[i]);
|
||||
while (buf_pool->n_pend_reads >= recv_n_pool_free_frames / 2) {
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
@@ -643,8 +650,8 @@ buf_read_recv_pages(
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin();
|
||||
/* Flush pages from the end of all the LRU lists if necessary */
|
||||
buf_flush_free_margins();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
|
@@ -403,8 +403,6 @@ ha_print_info(
|
||||
FILE* file, /*!< in: file where to print */
|
||||
hash_table_t* table) /*!< in: hash table */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
#ifdef UNIV_DEBUG
|
||||
/* Some of the code here is disabled for performance reasons in production
|
||||
builds, see http://bugs.mysql.com/36941 */
|
||||
@@ -418,6 +416,8 @@ builds, see http://bugs.mysql.com/36941 */
|
||||
#endif /* PRINT_USED_CELLS */
|
||||
ulint n_bufs;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
|
||||
#ifdef PRINT_USED_CELLS
|
||||
for (i = 0; i < hash_get_n_cells(table); i++) {
|
||||
|
||||
|
@@ -135,6 +135,7 @@ static long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
||||
static ulong innobase_commit_concurrency = 0;
|
||||
static ulong innobase_read_io_threads;
|
||||
static ulong innobase_write_io_threads;
|
||||
static long innobase_buffer_pool_instances = 1;
|
||||
|
||||
static long long innobase_buffer_pool_size, innobase_log_file_size;
|
||||
|
||||
@@ -241,7 +242,7 @@ static PSI_mutex_info all_innodb_mutexes[] = {
|
||||
{&file_format_max_mutex_key, "file_format_max_mutex", 0},
|
||||
{&fil_system_mutex_key, "fil_system_mutex", 0},
|
||||
{&flush_list_mutex_key, "flush_list_mutex", 0},
|
||||
{&flush_order_mutex_key, "flush_order_mutex", 0},
|
||||
{&log_flush_order_mutex_key, "log_flush_order_mutex", 0},
|
||||
{&hash_table_mutex_key, "hash_table_mutex", 0},
|
||||
{&ibuf_bitmap_mutex_key, "ibuf_bitmap_mutex", 0},
|
||||
{&ibuf_mutex_key, "ibuf_mutex", 0},
|
||||
@@ -2305,6 +2306,7 @@ innobase_change_buffering_inited_ok:
|
||||
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
|
||||
|
||||
srv_buf_pool_size = (ulint) innobase_buffer_pool_size;
|
||||
srv_buf_pool_instances = (ulint) innobase_buffer_pool_instances;
|
||||
|
||||
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
|
||||
|
||||
@@ -2348,9 +2350,6 @@ innobase_change_buffering_inited_ok:
|
||||
ut_a(0 == strcmp(my_charset_latin1.name, "latin1_swedish_ci"));
|
||||
srv_latin1_ordering = my_charset_latin1.sort_order;
|
||||
|
||||
innobase_old_blocks_pct = buf_LRU_old_ratio_update(
|
||||
innobase_old_blocks_pct, FALSE);
|
||||
|
||||
innobase_commit_concurrency_init_default();
|
||||
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
@@ -2404,6 +2403,9 @@ innobase_change_buffering_inited_ok:
|
||||
goto mem_free_and_error;
|
||||
}
|
||||
|
||||
innobase_old_blocks_pct = buf_LRU_old_ratio_update(
|
||||
innobase_old_blocks_pct, TRUE);
|
||||
|
||||
innobase_open_tables = hash_create(200);
|
||||
mysql_mutex_init(innobase_share_mutex_key,
|
||||
&innobase_share_mutex,
|
||||
@@ -3337,6 +3339,8 @@ innobase_build_index_translation(
|
||||
|
||||
DBUG_ENTER("innobase_build_index_translation");
|
||||
|
||||
mutex_enter(&dict_sys->mutex);
|
||||
|
||||
mysql_num_index = table->s->keys;
|
||||
ib_num_index = UT_LIST_GET_LEN(ib_table->indexes);
|
||||
|
||||
@@ -3367,6 +3371,13 @@ innobase_build_index_translation(
|
||||
MYF(MY_ALLOW_ZERO_PTR));
|
||||
|
||||
if (!index_mapping) {
|
||||
/* Report an error if index_mapping continues to be
|
||||
NULL and mysql_num_index is a non-zero value */
|
||||
sql_print_error("InnoDB: fail to allocate memory for "
|
||||
"index translation table. Number of "
|
||||
"Index:%lu, array size:%lu",
|
||||
mysql_num_index,
|
||||
share->idx_trans_tbl.array_size);
|
||||
ret = FALSE;
|
||||
goto func_exit;
|
||||
}
|
||||
@@ -3374,7 +3385,6 @@ innobase_build_index_translation(
|
||||
share->idx_trans_tbl.array_size = mysql_num_index;
|
||||
}
|
||||
|
||||
|
||||
/* For each index in the mysql key_info array, fetch its
|
||||
corresponding InnoDB index pointer into index_mapping
|
||||
array. */
|
||||
@@ -3420,6 +3430,8 @@ func_exit:
|
||||
|
||||
share->idx_trans_tbl.index_mapping = index_mapping;
|
||||
|
||||
mutex_exit(&dict_sys->mutex);
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
@@ -10813,6 +10825,11 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
|
||||
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
|
||||
NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
|
||||
|
||||
static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
"Number of buffer pool instances, set to higher value on high-end machines to increase scalability",
|
||||
NULL, NULL, 1L, 1L, MAX_BUFFER_POOLS, 1L);
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(commit_concurrency, innobase_commit_concurrency,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Helps in performance tuning in heavily concurrent environments.",
|
||||
@@ -10948,6 +10965,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||
MYSQL_SYSVAR(additional_mem_pool_size),
|
||||
MYSQL_SYSVAR(autoextend_increment),
|
||||
MYSQL_SYSVAR(buffer_pool_size),
|
||||
MYSQL_SYSVAR(buffer_pool_instances),
|
||||
MYSQL_SYSVAR(checksums),
|
||||
MYSQL_SYSVAR(commit_concurrency),
|
||||
MYSQL_SYSVAR(concurrency_tickets),
|
||||
|
@@ -1307,6 +1307,14 @@ static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
|
||||
STRUCT_FLD(old_name, "Buddy Block Size"),
|
||||
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
|
||||
|
||||
{STRUCT_FLD(field_name, "buffer_pool_instance"),
|
||||
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
|
||||
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
|
||||
STRUCT_FLD(value, 0),
|
||||
STRUCT_FLD(field_flags, 0),
|
||||
STRUCT_FLD(old_name, "Buffer Pool Id"),
|
||||
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
|
||||
|
||||
{STRUCT_FLD(field_name, "pages_used"),
|
||||
STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
|
||||
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
|
||||
@@ -1356,8 +1364,8 @@ i_s_cmpmem_fill_low(
|
||||
COND* cond, /*!< in: condition (ignored) */
|
||||
ibool reset) /*!< in: TRUE=reset cumulated counts */
|
||||
{
|
||||
int status = 0;
|
||||
TABLE* table = (TABLE *) tables->table;
|
||||
int status = 0;
|
||||
|
||||
DBUG_ENTER("i_s_cmpmem_fill_low");
|
||||
|
||||
@@ -1369,33 +1377,50 @@ i_s_cmpmem_fill_low(
|
||||
|
||||
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
|
||||
for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
|
||||
buf_buddy_stat_t* buddy_stat = &buf_buddy_stat[x];
|
||||
status = 0;
|
||||
|
||||
table->field[0]->store(BUF_BUDDY_LOW << x);
|
||||
table->field[1]->store(buddy_stat->used);
|
||||
table->field[2]->store(UNIV_LIKELY(x < BUF_BUDDY_SIZES)
|
||||
? UT_LIST_GET_LEN(buf_pool->zip_free[x])
|
||||
: 0);
|
||||
table->field[3]->store((longlong) buddy_stat->relocated, true);
|
||||
table->field[4]->store(
|
||||
(ulong) (buddy_stat->relocated_usec / 1000000));
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
|
||||
if (reset) {
|
||||
/* This is protected by buf_pool_mutex. */
|
||||
buddy_stat->relocated = 0;
|
||||
buddy_stat->relocated_usec = 0;
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
|
||||
buf_buddy_stat_t* buddy_stat;
|
||||
|
||||
buddy_stat = &buf_pool->buddy_stat[x];
|
||||
|
||||
table->field[0]->store(BUF_BUDDY_LOW << x);
|
||||
table->field[1]->store(i);
|
||||
table->field[2]->store(buddy_stat->used);
|
||||
table->field[3]->store(UNIV_LIKELY(x < BUF_BUDDY_SIZES)
|
||||
? UT_LIST_GET_LEN(buf_pool->zip_free[x])
|
||||
: 0);
|
||||
table->field[4]->store((longlong)
|
||||
buddy_stat->relocated, true);
|
||||
table->field[5]->store(
|
||||
(ulong) (buddy_stat->relocated_usec / 1000000));
|
||||
|
||||
if (reset) {
|
||||
/* This is protected by buf_pool->mutex. */
|
||||
buddy_stat->relocated = 0;
|
||||
buddy_stat->relocated_usec = 0;
|
||||
}
|
||||
|
||||
if (schema_table_store_record(thd, table)) {
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (schema_table_store_record(thd, table)) {
|
||||
status = 1;
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
if (status) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
DBUG_RETURN(status);
|
||||
}
|
||||
|
||||
|
@@ -2323,7 +2323,7 @@ ibuf_get_merge_page_nos(
|
||||
|
||||
*n_stored = 0;
|
||||
|
||||
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool->curr_size / 4);
|
||||
limit = ut_min(IBUF_MAX_N_PAGES_MERGED, buf_pool_get_curr_size() / 4);
|
||||
|
||||
if (page_rec_is_supremum(rec)) {
|
||||
|
||||
@@ -3139,9 +3139,9 @@ ibuf_set_entry_counter(
|
||||
ibool is_optimistic, /*!< in: is this an optimistic insert */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ulint counter;
|
||||
dfield_t* field;
|
||||
byte* data;
|
||||
ulint counter = 0;
|
||||
|
||||
/* pcur points to either a user rec or to a page's infimum record. */
|
||||
ut_ad(page_validate(btr_pcur_get_page(pcur), ibuf->index));
|
||||
@@ -3682,10 +3682,11 @@ check_watch:
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
ulint fold = buf_page_address_fold(space, page_no);
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, page_no);
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
bpage = buf_page_hash_get_low(space, page_no, fold);
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
bpage = buf_page_hash_get_low(buf_pool, space, page_no, fold);
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
if (UNIV_LIKELY_NULL(bpage)) {
|
||||
/* A buffer pool watch has been set or the
|
||||
|
@@ -36,22 +36,24 @@ Created December 2006 by Marko Makela
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool_mutex and must not hold buf_pool_zip_mutex or any
|
||||
block->mutex. The buf_pool_mutex may only be released and reacquired
|
||||
buf_pool->mutex and must not hold buf_pool_zip_mutex or any
|
||||
block->mutex. The buf_pool->mutex may only be released and reacquired
|
||||
if lru != NULL. This function should only be used for allocating
|
||||
compressed page frames or control blocks (buf_page_t). Allocated
|
||||
control blocks must be properly initialized immediately after
|
||||
buf_buddy_alloc() has returned the memory, before releasing
|
||||
buf_pool_mutex.
|
||||
buf_pool->mutex.
|
||||
@return allocated block, possibly NULL if lru == NULL */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
buf_buddy_alloc(
|
||||
/*============*/
|
||||
buf_pool_t* buf_pool,
|
||||
/*!< buffer pool in which the block resides */
|
||||
ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
|
||||
ibool* lru) /*!< in: pointer to a variable that will be assigned
|
||||
TRUE if storage was allocated from the LRU list
|
||||
and buf_pool_mutex was temporarily released,
|
||||
and buf_pool->mutex was temporarily released,
|
||||
or NULL if the LRU list should not be used */
|
||||
__attribute__((malloc));
|
||||
|
||||
@@ -61,28 +63,13 @@ UNIV_INLINE
|
||||
void
|
||||
buf_buddy_free(
|
||||
/*===========*/
|
||||
buf_pool_t* buf_pool,
|
||||
/*!< buffer pool in which the block resides */
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint size) /*!< in: block size, up to UNIV_PAGE_SIZE */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Statistics of buddy blocks of a given size. */
|
||||
struct buf_buddy_stat_struct {
|
||||
/** Number of blocks allocated from the buddy system. */
|
||||
ulint used;
|
||||
/** Number of blocks relocated by the buddy system. */
|
||||
ib_uint64_t relocated;
|
||||
/** Total duration of block relocations, in microseconds. */
|
||||
ib_uint64_t relocated_usec;
|
||||
};
|
||||
|
||||
/** Statistics of buddy blocks of a given size. */
|
||||
typedef struct buf_buddy_stat_struct buf_buddy_stat_t;
|
||||
|
||||
/** Statistics of the buddy system, indexed by block size.
|
||||
Protected by buf_pool_mutex. */
|
||||
extern buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
# include "buf0buddy.ic"
|
||||
#endif
|
||||
|
@@ -35,18 +35,20 @@ Created December 2006 by Marko Makela
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool_mutex and must not hold buf_pool_zip_mutex or any block->mutex.
|
||||
The buf_pool_mutex may only be released and reacquired if lru != NULL.
|
||||
buf_pool->mutex and must not hold buf_pool_zip_mutex or any block->mutex.
|
||||
The buf_pool->mutex may only be released and reacquired if lru != NULL.
|
||||
@return allocated block, possibly NULL if lru==NULL */
|
||||
UNIV_INTERN
|
||||
void*
|
||||
buf_buddy_alloc_low(
|
||||
/*================*/
|
||||
buf_pool_t* buf_pool,
|
||||
/*!< in: buffer pool in which the page resides */
|
||||
ulint i, /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
ibool* lru) /*!< in: pointer to a variable that will be assigned
|
||||
TRUE if storage was allocated from the LRU list
|
||||
and buf_pool_mutex was temporarily released,
|
||||
and buf_pool->mutex was temporarily released,
|
||||
or NULL if the LRU list should not be used */
|
||||
__attribute__((malloc));
|
||||
|
||||
@@ -56,10 +58,11 @@ UNIV_INTERN
|
||||
void
|
||||
buf_buddy_free_low(
|
||||
/*===============*/
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint i) /*!< in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/**********************************************************************//**
|
||||
@@ -83,27 +86,32 @@ buf_buddy_get_slot(
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool_mutex and must not hold buf_pool_zip_mutex or any
|
||||
block->mutex. The buf_pool_mutex may only be released and reacquired
|
||||
buf_pool->mutex and must not hold buf_pool_zip_mutex or any
|
||||
block->mutex. The buf_pool->mutex may only be released and reacquired
|
||||
if lru != NULL. This function should only be used for allocating
|
||||
compressed page frames or control blocks (buf_page_t). Allocated
|
||||
control blocks must be properly initialized immediately after
|
||||
buf_buddy_alloc() has returned the memory, before releasing
|
||||
buf_pool_mutex.
|
||||
buf_pool->mutex.
|
||||
@return allocated block, possibly NULL if lru == NULL */
|
||||
UNIV_INLINE
|
||||
void*
|
||||
buf_buddy_alloc(
|
||||
/*============*/
|
||||
ulint size, /*!< in: block size, up to UNIV_PAGE_SIZE */
|
||||
ibool* lru) /*!< in: pointer to a variable that will be assigned
|
||||
TRUE if storage was allocated from the LRU list
|
||||
and buf_pool_mutex was temporarily released,
|
||||
or NULL if the LRU list should not be used */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool in which
|
||||
the page resides */
|
||||
ulint size, /*!< in: block size, up to
|
||||
UNIV_PAGE_SIZE */
|
||||
ibool* lru) /*!< in: pointer to a variable
|
||||
that will be assigned TRUE if
|
||||
storage was allocated from the
|
||||
LRU list and buf_pool->mutex was
|
||||
temporarily released, or NULL if
|
||||
the LRU list should not be used */
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
|
||||
return(buf_buddy_alloc_low(buf_buddy_get_slot(size), lru));
|
||||
return(buf_buddy_alloc_low(buf_pool, buf_buddy_get_slot(size), lru));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
@@ -112,13 +120,15 @@ UNIV_INLINE
|
||||
void
|
||||
buf_buddy_free(
|
||||
/*===========*/
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint size) /*!< in: block size, up to UNIV_PAGE_SIZE */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
void* buf, /*!< in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint size) /*!< in: block size, up to
|
||||
UNIV_PAGE_SIZE */
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
|
||||
buf_buddy_free_low(buf, buf_buddy_get_slot(size));
|
||||
buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
|
||||
}
|
||||
|
||||
#ifdef UNIV_MATERIALIZE
|
||||
|
@@ -63,7 +63,14 @@ Created 11/5/1995 Heikki Tuuri
|
||||
position of the block. */
|
||||
/* @} */
|
||||
|
||||
extern buf_pool_t* buf_pool; /*!< The buffer pool of the database */
|
||||
#define MAX_BUFFER_POOLS 64 /*!< The maximum number of buffer
|
||||
pools that can be defined */
|
||||
|
||||
#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent
|
||||
buffer pool watches */
|
||||
|
||||
extern buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS]; /*!< The buffer pools
|
||||
of the database */
|
||||
#ifdef UNIV_DEBUG
|
||||
extern ibool buf_debug_prints;/*!< If this is set TRUE, the program
|
||||
prints info whenever read or flush
|
||||
@@ -71,6 +78,8 @@ extern ibool buf_debug_prints;/*!< If this is set TRUE, the program
|
||||
#endif /* UNIV_DEBUG */
|
||||
extern ulint srv_buf_pool_write_requests; /*!< variable to count write request
|
||||
issued */
|
||||
extern ulint srv_buf_pool_instances;
|
||||
extern ulint srv_buf_pool_curr_size;
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
extern buf_block_t* back_block1; /*!< first block, for --apply-log */
|
||||
extern buf_block_t* back_block2; /*!< second block, for page reorganize */
|
||||
@@ -108,20 +117,37 @@ enum buf_page_state {
|
||||
};
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/********************************************************************//**
|
||||
Acquire mutex on all buffer pool instances */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_pool_mutex_enter_all(void);
|
||||
/*===========================*/
|
||||
|
||||
/********************************************************************//**
|
||||
Release mutex on all buffer pool instances */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_pool_mutex_exit_all(void);
|
||||
/*==========================*/
|
||||
|
||||
/********************************************************************//**
|
||||
Creates the buffer pool.
|
||||
@return own: buf_pool object, NULL if not enough memory or error */
|
||||
UNIV_INTERN
|
||||
buf_pool_t*
|
||||
buf_pool_init(void);
|
||||
/*===============*/
|
||||
ulint
|
||||
buf_pool_init(
|
||||
/*=========*/
|
||||
ulint size, /*!< in: Size of the total pool in bytes */
|
||||
ulint n_instances); /*!< in: Number of instances */
|
||||
/********************************************************************//**
|
||||
Frees the buffer pool at shutdown. This must not be invoked before
|
||||
freeing all mutexes. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_pool_free(void);
|
||||
/*===============*/
|
||||
buf_pool_free(
|
||||
/*==========*/
|
||||
ulint n_instances); /*!< in: numbere of instances to free */
|
||||
|
||||
/********************************************************************//**
|
||||
Drops the adaptive hash index. To prevent a livelock, this function
|
||||
@@ -158,23 +184,31 @@ UNIV_INLINE
|
||||
ulint
|
||||
buf_pool_get_curr_size(void);
|
||||
/*========================*/
|
||||
/*********************************************************************//**
|
||||
Gets the current size of buffer buf_pool in frames.
|
||||
@return size in pages */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_pool_get_n_pages(void);
|
||||
/*=======================*/
|
||||
/********************************************************************//**
|
||||
Gets the smallest oldest_modification lsn for any page in the pool. Returns
|
||||
zero if all modified pages have been flushed to disk.
|
||||
@return oldest modification in pool, zero if none */
|
||||
UNIV_INLINE
|
||||
UNIV_INTERN
|
||||
ib_uint64_t
|
||||
buf_pool_get_oldest_modification(void);
|
||||
/*==================================*/
|
||||
/********************************************************************//**
|
||||
Allocates a buffer block.
|
||||
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
|
||||
UNIV_INLINE
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_block_alloc(
|
||||
/*============*/
|
||||
ulint zip_size); /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
ulint zip_size); /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
/********************************************************************//**
|
||||
Frees a buffer block which does not contain a file page. */
|
||||
UNIV_INLINE
|
||||
@@ -454,7 +488,7 @@ buf_page_get_newest_modification(
|
||||
page frame */
|
||||
/********************************************************************//**
|
||||
Increments the modify clock of a frame by 1. The caller must (1) own the
|
||||
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
|
||||
buf_pool->mutex and block bufferfix count has to be zero, (2) or own an x-lock
|
||||
on the block. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
@@ -536,7 +570,8 @@ UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_pool_contains_zip(
|
||||
/*==================*/
|
||||
const void* data); /*!< in: pointer to compressed page */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
const void* data); /*!< in: pointer to compressed page */
|
||||
#endif /* UNIV_DEBUG */
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/*********************************************************************//**
|
||||
@@ -610,8 +645,15 @@ buf_get_modified_ratio_pct(void);
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_refresh_io_stats(void);
|
||||
/*======================*/
|
||||
buf_refresh_io_stats(
|
||||
/*=================*/
|
||||
buf_pool_t* buf_pool); /*!< buffer pool instance */
|
||||
/**********************************************************************//**
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_refresh_io_stats_all(void);
|
||||
/*=================*/
|
||||
/*********************************************************************//**
|
||||
Asserts that all file pages in the buffer are in a replaceable state.
|
||||
@return TRUE */
|
||||
@@ -992,15 +1034,51 @@ buf_page_address_fold(
|
||||
ulint offset) /*!< in: offset of the page within space */
|
||||
__attribute__((const));
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given a page instance
|
||||
@return buf_pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_from_bpage(
|
||||
/*================*/
|
||||
const buf_page_t* bpage); /*!< in: buffer pool page */
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given a block instance
|
||||
@return buf_pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_from_block(
|
||||
/*================*/
|
||||
const buf_block_t* block); /*!< in: block */
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given space and offset of page
|
||||
@return buffer pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_get(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset);/*!< in: offset of the page within space */
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given its array index
|
||||
@return buffer pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_from_array(
|
||||
/*====================*/
|
||||
ulint index); /*!< in: array index to get buffer pool instance from */
|
||||
/******************************************************************//**
|
||||
Returns the control block of a file page, NULL if not found.
|
||||
@return block, NULL if not found */
|
||||
UNIV_INLINE
|
||||
buf_page_t*
|
||||
buf_page_hash_get_low(
|
||||
/*==================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset, /*!< in: offset of the page within space */
|
||||
ulint fold); /*!< in: buf_page_address_fold(space, offset) */
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset, /*!< in: offset of the page
|
||||
within space */
|
||||
ulint fold); /*!< in: buf_page_address_fold(
|
||||
space, offset) */
|
||||
/******************************************************************//**
|
||||
Returns the control block of a file page, NULL if not found.
|
||||
@return block, NULL if not found or not a real control block */
|
||||
@@ -1008,8 +1086,10 @@ UNIV_INLINE
|
||||
buf_page_t*
|
||||
buf_page_hash_get(
|
||||
/*==============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset);/*!< in: offset of the page within space */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset); /*!< in: offset of the page
|
||||
within space */
|
||||
/******************************************************************//**
|
||||
Returns the control block of a file page, NULL if not found
|
||||
or an uncompressed page frame does not exist.
|
||||
@@ -1018,8 +1098,10 @@ UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_block_hash_get(
|
||||
/*===============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset);/*!< in: offset of the page within space */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset); /*!< in: offset of the page
|
||||
within space */
|
||||
/*********************************************************************//**
|
||||
Gets the current length of the free list of buffer blocks.
|
||||
@return length of the free list */
|
||||
@@ -1033,9 +1115,10 @@ Determine if a block is a sentinel for a buffer pool watch.
|
||||
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_pool_watch_is(
|
||||
/*==============*/
|
||||
const buf_page_t* bpage) /*!< in: block */
|
||||
buf_pool_watch_is_sentinel(
|
||||
/*=======================*/
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
const buf_page_t* bpage) /*!< in: block */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/****************************************************************//**
|
||||
Add watch for the given page to be read in. Caller must have the buffer pool
|
||||
@@ -1069,6 +1152,23 @@ buf_pool_watch_occurred(
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset) /*!< in: page number */
|
||||
__attribute__((warn_unused_result));
|
||||
/********************************************************************//**
|
||||
Get total buffer pool statistics. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_get_total_list_len(
|
||||
/*===================*/
|
||||
ulint* LRU_len, /*!< out: length of all LRU lists */
|
||||
ulint* free_len, /*!< out: length of all free lists */
|
||||
ulint* flush_list_len);/*!< out: length of all flush lists */
|
||||
/********************************************************************//**
|
||||
Get total buffer pool statistics. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_get_total_stat(
|
||||
/*===============*/
|
||||
buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/** The common buffer control block structure
|
||||
@@ -1078,18 +1178,18 @@ struct buf_page_struct{
|
||||
/** @name General fields
|
||||
None of these bit-fields must be modified without holding
|
||||
buf_page_get_mutex() [buf_block_struct::mutex or
|
||||
buf_pool_zip_mutex], since they can be stored in the same
|
||||
buf_pool->zip_mutex], since they can be stored in the same
|
||||
machine word. Some of these fields are additionally protected
|
||||
by buf_pool_mutex. */
|
||||
by buf_pool->mutex. */
|
||||
/* @{ */
|
||||
|
||||
unsigned space:32; /*!< tablespace id; also protected
|
||||
by buf_pool_mutex. */
|
||||
by buf_pool->mutex. */
|
||||
unsigned offset:32; /*!< page number; also protected
|
||||
by buf_pool_mutex. */
|
||||
by buf_pool->mutex. */
|
||||
|
||||
unsigned state:3; /*!< state of the control block; also
|
||||
protected by buf_pool_mutex.
|
||||
protected by buf_pool->mutex.
|
||||
State transitions from
|
||||
BUF_BLOCK_READY_FOR_USE to
|
||||
BUF_BLOCK_MEMORY need not be
|
||||
@@ -1101,7 +1201,7 @@ struct buf_page_struct{
|
||||
flush_type.
|
||||
@see enum buf_flush */
|
||||
unsigned io_fix:2; /*!< type of pending I/O operation;
|
||||
also protected by buf_pool_mutex
|
||||
also protected by buf_pool->mutex
|
||||
@see enum buf_io_fix */
|
||||
unsigned buf_fix_count:25;/*!< count of how manyfold this block
|
||||
is currently bufferfixed */
|
||||
@@ -1190,8 +1290,8 @@ struct buf_page_struct{
|
||||
any one of the two mutexes */
|
||||
/* @} */
|
||||
/** @name LRU replacement algorithm fields
|
||||
These fields are protected by buf_pool_mutex only (not
|
||||
buf_pool_zip_mutex or buf_block_struct::mutex). */
|
||||
These fields are protected by buf_pool->mutex only (not
|
||||
buf_pool->zip_mutex or buf_block_struct::mutex). */
|
||||
/* @{ */
|
||||
|
||||
UT_LIST_NODE_T(buf_page_t) LRU;
|
||||
@@ -1221,6 +1321,8 @@ struct buf_page_struct{
|
||||
frees a page in buffer pool */
|
||||
# endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
buf_pool_t* buf_pool; /*!< buffer pool instance this
|
||||
page belongs to */
|
||||
};
|
||||
|
||||
/** The buffer control block structure */
|
||||
@@ -1260,7 +1362,7 @@ struct buf_block_struct{
|
||||
unsigned lock_hash_val:32;/*!< hashed value of the page address
|
||||
in the record lock hash table;
|
||||
protected by buf_block_t::lock
|
||||
(or buf_block_t::mutex, buf_pool_mutex
|
||||
(or buf_block_t::mutex, buf_pool->mutex
|
||||
in buf_page_get_gen(),
|
||||
buf_page_init_for_read()
|
||||
and buf_page_create()) */
|
||||
@@ -1389,6 +1491,16 @@ struct buf_pool_stat_struct{
|
||||
buf_page_peek_if_too_old() */
|
||||
};
|
||||
|
||||
/** Statistics of buddy blocks of a given size. */
|
||||
struct buf_buddy_stat_struct {
|
||||
/** Number of blocks allocated from the buddy system. */
|
||||
ulint used;
|
||||
/** Number of blocks relocated by the buddy system. */
|
||||
ib_uint64_t relocated;
|
||||
/** Total duration of block relocations, in microseconds. */
|
||||
ib_uint64_t relocated_usec;
|
||||
};
|
||||
|
||||
/** @brief The buffer pool structure.
|
||||
|
||||
NOTE! The definition appears here only for other modules of this
|
||||
@@ -1398,7 +1510,25 @@ struct buf_pool_struct{
|
||||
|
||||
/** @name General fields */
|
||||
/* @{ */
|
||||
|
||||
mutex_t mutex; /*!< Buffer pool mutex of this
|
||||
instance */
|
||||
mutex_t zip_mutex; /*!< Zip mutex of this buffer
|
||||
pool instance, protects compressed
|
||||
only pages (of type buf_page_t, not
|
||||
buf_block_t */
|
||||
ulint instance_no; /*!< Array index of this buffer
|
||||
pool instance */
|
||||
ulint old_pool_size; /*!< Old pool size in bytes */
|
||||
ulint curr_pool_size; /*!< Current pool size in bytes */
|
||||
ulint LRU_old_ratio; /*!< Reserve this much of the buffer
|
||||
pool for "old" blocks */
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint buddy_n_frames; /*!< Number of frames allocated from
|
||||
the buffer pool to the buddy system */
|
||||
#endif
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
ulint mutex_exit_forbidden; /*!< Forbid release mutex */
|
||||
#endif
|
||||
ulint n_chunks; /*!< number of buffer pool chunks */
|
||||
buf_chunk_t* chunks; /*!< buffer pool chunks */
|
||||
ulint curr_size; /*!< current pool size in pages */
|
||||
@@ -1410,12 +1540,16 @@ struct buf_pool_struct{
|
||||
whose frames are allocated to the
|
||||
zip buddy system,
|
||||
indexed by block->frame */
|
||||
ulint n_pend_reads; /*!< number of pending read operations */
|
||||
ulint n_pend_reads; /*!< number of pending read
|
||||
operations */
|
||||
ulint n_pend_unzip; /*!< number of pending decompressions */
|
||||
|
||||
time_t last_printout_time;
|
||||
/*!< when buf_print_io was last time
|
||||
called */
|
||||
buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES + 1];
|
||||
/*!< Statistics of buddy system,
|
||||
indexed by block size */
|
||||
buf_pool_stat_t stat; /*!< current statistics */
|
||||
buf_pool_stat_t old_stat; /*!< old statistics */
|
||||
|
||||
@@ -1432,14 +1566,6 @@ struct buf_pool_struct{
|
||||
the bpage is on flush_list. It
|
||||
also protects writes to
|
||||
bpage::oldest_modification */
|
||||
mutex_t flush_order_mutex;/*!< mutex to serialize access to
|
||||
the flush list when we are putting
|
||||
dirty blocks in the list. The idea
|
||||
behind this mutex is to be able
|
||||
to release log_sys->mutex during
|
||||
mtr_commit and still ensure that
|
||||
insertions in the flush_list happen
|
||||
in the LSN order. */
|
||||
UT_LIST_BASE_NODE_T(buf_page_t) flush_list;
|
||||
/*!< base node of the modified block
|
||||
list */
|
||||
@@ -1519,6 +1645,12 @@ struct buf_pool_struct{
|
||||
/*!< unmodified compressed pages */
|
||||
UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES];
|
||||
/*!< buddy free lists */
|
||||
|
||||
buf_page_t watch[BUF_POOL_WATCH_SIZE];
|
||||
/*!< Sentinel records for buffer
|
||||
pool watches. Protected by
|
||||
buf_pool->mutex. */
|
||||
|
||||
#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
|
||||
# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
|
||||
#endif
|
||||
@@ -1540,65 +1672,51 @@ Use these instead of accessing buf_pool_mutex directly. */
|
||||
/* @{ */
|
||||
|
||||
/** Test if buf_pool_mutex is owned. */
|
||||
#define buf_pool_mutex_own() mutex_own(&buf_pool_mutex)
|
||||
#define buf_pool_mutex_own(b) mutex_own(&b->mutex)
|
||||
/** Acquire the buffer pool mutex. */
|
||||
#define buf_pool_mutex_enter() do { \
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex)); \
|
||||
mutex_enter(&buf_pool_mutex); \
|
||||
#define buf_pool_mutex_enter(b) do { \
|
||||
ut_ad(!mutex_own(&b->zip_mutex)); \
|
||||
mutex_enter(&b->mutex); \
|
||||
} while (0)
|
||||
|
||||
/** Test if flush list mutex is owned. */
|
||||
#define buf_flush_list_mutex_own() mutex_own(&buf_pool->flush_list_mutex)
|
||||
#define buf_flush_list_mutex_own(b) mutex_own(&b->flush_list_mutex)
|
||||
|
||||
/** Acquire the flush list mutex. */
|
||||
#define buf_flush_list_mutex_enter() do { \
|
||||
mutex_enter(&buf_pool->flush_list_mutex); \
|
||||
#define buf_flush_list_mutex_enter(b) do { \
|
||||
mutex_enter(&b->flush_list_mutex); \
|
||||
} while (0)
|
||||
/** Release the flush list mutex. */
|
||||
# define buf_flush_list_mutex_exit() do { \
|
||||
mutex_exit(&buf_pool->flush_list_mutex); \
|
||||
# define buf_flush_list_mutex_exit(b) do { \
|
||||
mutex_exit(&b->flush_list_mutex); \
|
||||
} while (0)
|
||||
|
||||
/** Test if flush order mutex is owned. */
|
||||
#define buf_flush_order_mutex_own() mutex_own(&buf_pool->flush_order_mutex)
|
||||
|
||||
/** Acquire the flush order mutex. */
|
||||
#define buf_flush_order_mutex_enter() do { \
|
||||
mutex_enter(&buf_pool->flush_order_mutex); \
|
||||
} while (0)
|
||||
/** Release the flush order mutex. */
|
||||
# define buf_flush_order_mutex_exit() do { \
|
||||
mutex_exit(&buf_pool->flush_order_mutex); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
||||
/** Flag to forbid the release of the buffer pool mutex.
|
||||
Protected by buf_pool_mutex. */
|
||||
extern ulint buf_pool_mutex_exit_forbidden;
|
||||
/** Forbid the release of the buffer pool mutex. */
|
||||
# define buf_pool_mutex_exit_forbid() do { \
|
||||
ut_ad(buf_pool_mutex_own()); \
|
||||
buf_pool_mutex_exit_forbidden++; \
|
||||
# define buf_pool_mutex_exit_forbid(b) do { \
|
||||
ut_ad(buf_pool_mutex_own(b)); \
|
||||
b->mutex_exit_forbidden++; \
|
||||
} while (0)
|
||||
/** Allow the release of the buffer pool mutex. */
|
||||
# define buf_pool_mutex_exit_allow() do { \
|
||||
ut_ad(buf_pool_mutex_own()); \
|
||||
ut_a(buf_pool_mutex_exit_forbidden); \
|
||||
buf_pool_mutex_exit_forbidden--; \
|
||||
# define buf_pool_mutex_exit_allow(b) do { \
|
||||
ut_ad(buf_pool_mutex_own(b)); \
|
||||
ut_a(b->mutex_exit_forbidden); \
|
||||
b->mutex_exit_forbidden--; \
|
||||
} while (0)
|
||||
/** Release the buffer pool mutex. */
|
||||
# define buf_pool_mutex_exit() do { \
|
||||
ut_a(!buf_pool_mutex_exit_forbidden); \
|
||||
mutex_exit(&buf_pool_mutex); \
|
||||
# define buf_pool_mutex_exit(b) do { \
|
||||
ut_a(!b->mutex_exit_forbidden); \
|
||||
mutex_exit(&b->mutex); \
|
||||
} while (0)
|
||||
#else
|
||||
/** Forbid the release of the buffer pool mutex. */
|
||||
# define buf_pool_mutex_exit_forbid() ((void) 0)
|
||||
# define buf_pool_mutex_exit_forbid(b) ((void) 0)
|
||||
/** Allow the release of the buffer pool mutex. */
|
||||
# define buf_pool_mutex_exit_allow() ((void) 0)
|
||||
# define buf_pool_mutex_exit_allow(b) ((void) 0)
|
||||
/** Release the buffer pool mutex. */
|
||||
# define buf_pool_mutex_exit() mutex_exit(&buf_pool_mutex)
|
||||
# define buf_pool_mutex_exit(b) mutex_exit(&b->mutex)
|
||||
#endif
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/* @} */
|
||||
|
@@ -31,11 +31,32 @@ Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "mtr0mtr.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "buf0flu.h"
|
||||
#include "buf0lru.h"
|
||||
#include "buf0rea.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the current size of buffer buf_pool in bytes.
|
||||
@return size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_pool_get_curr_size(void)
|
||||
/*========================*/
|
||||
{
|
||||
return(srv_buf_pool_curr_size);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the current size of buffer buf_pool in pages.
|
||||
@return size in pages*/
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_pool_get_n_pages(void)
|
||||
/*======================*/
|
||||
{
|
||||
return(buf_pool_get_curr_size() / UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Reads the freed_page_clock of a buffer block.
|
||||
@return freed_page_clock */
|
||||
@@ -45,7 +66,7 @@ buf_page_get_freed_page_clock(
|
||||
/*==========================*/
|
||||
const buf_page_t* bpage) /*!< in: block */
|
||||
{
|
||||
/* This is sometimes read without holding buf_pool_mutex. */
|
||||
/* This is sometimes read without holding buf_pool->mutex. */
|
||||
return(bpage->freed_page_clock);
|
||||
}
|
||||
|
||||
@@ -72,6 +93,8 @@ buf_page_peek_if_too_old(
|
||||
/*=====================*/
|
||||
const buf_page_t* bpage) /*!< in: block to make younger */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
|
||||
if (UNIV_UNLIKELY(buf_pool->freed_page_clock == 0)) {
|
||||
/* If eviction has not started yet, do not update the
|
||||
statistics or move blocks in the LRU list. This is
|
||||
@@ -93,54 +116,11 @@ buf_page_peek_if_too_old(
|
||||
return((buf_pool->freed_page_clock & ((1UL << 31) - 1))
|
||||
> ((ulint) bpage->freed_page_clock
|
||||
+ (buf_pool->curr_size
|
||||
* (BUF_LRU_OLD_RATIO_DIV - buf_LRU_old_ratio)
|
||||
* (BUF_LRU_OLD_RATIO_DIV - buf_pool->LRU_old_ratio)
|
||||
/ (BUF_LRU_OLD_RATIO_DIV * 4))));
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the current size of buffer buf_pool in bytes.
|
||||
@return size in bytes */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
buf_pool_get_curr_size(void)
|
||||
/*========================*/
|
||||
{
|
||||
return(buf_pool->curr_size * UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Gets the smallest oldest_modification lsn for any page in the pool. Returns
|
||||
zero if all modified pages have been flushed to disk.
|
||||
@return oldest modification in pool, zero if none */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
buf_pool_get_oldest_modification(void)
|
||||
/*==================================*/
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
ib_uint64_t lsn;
|
||||
|
||||
buf_flush_list_mutex_enter();
|
||||
|
||||
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
|
||||
|
||||
if (bpage == NULL) {
|
||||
lsn = 0;
|
||||
} else {
|
||||
ut_ad(bpage->in_flush_list);
|
||||
lsn = bpage->oldest_modification;
|
||||
}
|
||||
|
||||
buf_flush_list_mutex_exit();
|
||||
|
||||
/* The returned answer may be out of date: the flush_list can
|
||||
change after the mutex has been released. */
|
||||
|
||||
return(lsn);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the state of a block.
|
||||
@return state */
|
||||
@@ -293,13 +273,15 @@ buf_page_get_mutex(
|
||||
/*===============*/
|
||||
const buf_page_t* bpage) /*!< in: pointer to control block */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
|
||||
switch (buf_page_get_state(bpage)) {
|
||||
case BUF_BLOCK_ZIP_FREE:
|
||||
ut_error;
|
||||
return(NULL);
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
case BUF_BLOCK_ZIP_DIRTY:
|
||||
return(&buf_pool_zip_mutex);
|
||||
return(&buf_pool->zip_mutex);
|
||||
default:
|
||||
return(&((buf_block_t*) bpage)->mutex);
|
||||
}
|
||||
@@ -385,7 +367,7 @@ Gets the io_fix state of a block.
|
||||
UNIV_INLINE
|
||||
enum buf_io_fix
|
||||
buf_block_get_io_fix(
|
||||
/*================*/
|
||||
/*=================*/
|
||||
const buf_block_t* block) /*!< in: pointer to the control block */
|
||||
{
|
||||
return(buf_page_get_io_fix(&block->page));
|
||||
@@ -400,7 +382,10 @@ buf_page_set_io_fix(
|
||||
buf_page_t* bpage, /*!< in/out: control block */
|
||||
enum buf_io_fix io_fix) /*!< in: io_fix state */
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
#ifdef UNIV_DEBUG
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
#endif
|
||||
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
|
||||
|
||||
bpage->io_fix = io_fix;
|
||||
@@ -428,7 +413,10 @@ buf_page_can_relocate(
|
||||
/*==================*/
|
||||
const buf_page_t* bpage) /*!< control block being relocated */
|
||||
{
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
#ifdef UNIV_DEBUG
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
#endif
|
||||
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
|
||||
ut_ad(buf_page_in_file(bpage));
|
||||
ut_ad(bpage->in_LRU_list);
|
||||
@@ -446,8 +434,11 @@ buf_page_is_old(
|
||||
/*============*/
|
||||
const buf_page_t* bpage) /*!< in: control block */
|
||||
{
|
||||
#ifdef UNIV_DEBUG
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
#endif
|
||||
ut_ad(buf_page_in_file(bpage));
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
return(bpage->old);
|
||||
}
|
||||
@@ -461,8 +452,11 @@ buf_page_set_old(
|
||||
buf_page_t* bpage, /*!< in/out: control block */
|
||||
ibool old) /*!< in: old */
|
||||
{
|
||||
#ifdef UNIV_DEBUG
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
#endif /* UNIV_DEBUG */
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(bpage->in_LRU_list);
|
||||
|
||||
#ifdef UNIV_LRU_DEBUG
|
||||
@@ -508,8 +502,11 @@ buf_page_set_accessed(
|
||||
buf_page_t* bpage, /*!< in/out: control block */
|
||||
ulint time_ms) /*!< in: ut_time_ms() */
|
||||
{
|
||||
#ifdef UNIV_DEBUG
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
#endif
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
if (!bpage->access_time) {
|
||||
/* Make this the time of the first access. */
|
||||
@@ -714,25 +711,6 @@ buf_block_get_lock_hash_val(
|
||||
return(block->lock_hash_val);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Allocates a buffer block.
|
||||
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_block_alloc(
|
||||
/*============*/
|
||||
ulint zip_size) /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
block = buf_LRU_get_free_block(zip_size);
|
||||
|
||||
buf_block_set_state(block, BUF_BLOCK_MEMORY);
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Frees a buffer block which does not contain a file page. */
|
||||
UNIV_INLINE
|
||||
@@ -741,7 +719,9 @@ buf_block_free(
|
||||
/*===========*/
|
||||
buf_block_t* block) /*!< in, own: block to be freed */
|
||||
{
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block);
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
@@ -751,7 +731,7 @@ buf_block_free(
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
@@ -825,7 +805,9 @@ buf_block_modify_clock_inc(
|
||||
buf_block_t* block) /*!< in: block */
|
||||
{
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad((buf_pool_mutex_own()
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage((buf_page_t*)block);
|
||||
|
||||
ut_ad((buf_pool_mutex_own(buf_pool)
|
||||
&& (block->page.buf_fix_count == 0))
|
||||
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
@@ -903,6 +885,66 @@ buf_block_buf_fix_dec(
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given a page instance
|
||||
@return buf_pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_from_bpage(
|
||||
/*================*/
|
||||
const buf_page_t* bpage) /*!< in: buffer pool page */
|
||||
{
|
||||
/* Every page must be in some buffer pool. */
|
||||
ut_ad(bpage->buf_pool != NULL);
|
||||
|
||||
return(bpage->buf_pool);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given a block instance
|
||||
@return buf_pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_from_block(
|
||||
/*================*/
|
||||
const buf_block_t* block) /*!< in: block */
|
||||
{
|
||||
return(buf_pool_from_bpage(&block->page));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given space and offset of page
|
||||
@return buffer pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_get(
|
||||
/*==========*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset) /*!< in: offset of the page within space */
|
||||
{
|
||||
ulint fold;
|
||||
ulint index;
|
||||
ulint ignored_offset;
|
||||
|
||||
ignored_offset = offset >> 6; /* 2log of BUF_READ_AHEAD_AREA (64)*/
|
||||
fold = buf_page_address_fold(space, ignored_offset);
|
||||
index = fold % srv_buf_pool_instances;
|
||||
return buf_pool_ptr[index];
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the buffer pool instance given its array index
|
||||
@return buffer pool */
|
||||
UNIV_INLINE
|
||||
buf_pool_t*
|
||||
buf_pool_from_array(
|
||||
/*================*/
|
||||
ulint index) /*!< in: array index to get
|
||||
buffer pool instance from */
|
||||
{
|
||||
return buf_pool_ptr[index];
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Returns the control block of a file page, NULL if not found.
|
||||
@return block, NULL if not found */
|
||||
@@ -910,14 +952,17 @@ UNIV_INLINE
|
||||
buf_page_t*
|
||||
buf_page_hash_get_low(
|
||||
/*==================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset, /*!< in: offset of the page within space */
|
||||
ulint fold) /*!< in: buf_page_address_fold(space, offset) */
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset, /*!< in: offset of the page
|
||||
within space */
|
||||
ulint fold) /*!< in: buf_page_address_fold(
|
||||
space, offset) */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(fold == buf_page_address_fold(space, offset));
|
||||
|
||||
/* Look for the page in the hash table */
|
||||
@@ -943,13 +988,17 @@ UNIV_INLINE
|
||||
buf_page_t*
|
||||
buf_page_hash_get(
|
||||
/*==============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset) /*!< in: offset of the page within space */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset) /*!< in: offset of the page
|
||||
within space */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
ulint fold = buf_page_address_fold(space, offset);
|
||||
buf_page_t* bpage = buf_page_hash_get_low(space, offset, fold);
|
||||
|
||||
if (bpage && UNIV_UNLIKELY(buf_pool_watch_is(bpage))) {
|
||||
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
|
||||
|
||||
if (bpage && buf_pool_watch_is_sentinel(buf_pool, bpage)) {
|
||||
bpage = NULL;
|
||||
}
|
||||
|
||||
@@ -964,12 +1013,14 @@ UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_block_hash_get(
|
||||
/*===============*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset) /*!< in: offset of the page within space */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset) /*!< in: offset of the page
|
||||
within space */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
block = buf_page_get_block(buf_page_hash_get(space, offset));
|
||||
block = buf_page_get_block(buf_page_hash_get(buf_pool, space, offset));
|
||||
|
||||
return(block);
|
||||
}
|
||||
@@ -989,12 +1040,13 @@ buf_page_peek(
|
||||
ulint offset) /*!< in: page number */
|
||||
{
|
||||
const buf_page_t* bpage;
|
||||
buf_pool_t* buf_pool = buf_pool_get(space, offset);
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
bpage = buf_page_hash_get(space, offset);
|
||||
bpage = buf_page_hash_get(buf_pool, space, offset);
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
return(bpage != NULL);
|
||||
}
|
||||
@@ -1008,6 +1060,7 @@ buf_page_release_zip(
|
||||
buf_page_t* bpage) /*!< in: buffer block */
|
||||
{
|
||||
buf_block_t* block;
|
||||
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
|
||||
|
||||
ut_ad(bpage);
|
||||
ut_a(bpage->buf_fix_count > 0);
|
||||
@@ -1015,9 +1068,9 @@ buf_page_release_zip(
|
||||
switch (buf_page_get_state(bpage)) {
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
case BUF_BLOCK_ZIP_DIRTY:
|
||||
mutex_enter(&buf_pool_zip_mutex);
|
||||
mutex_enter(&buf_pool->zip_mutex);
|
||||
bpage->buf_fix_count--;
|
||||
mutex_exit(&buf_pool_zip_mutex);
|
||||
mutex_exit(&buf_pool->zip_mutex);
|
||||
return;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
block = (buf_block_t*) bpage;
|
||||
@@ -1036,6 +1089,7 @@ buf_page_release_zip(
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
||||
@@ -1087,4 +1141,37 @@ buf_block_dbg_add_level(
|
||||
sync_thread_add_level(&block->lock, level);
|
||||
}
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
/********************************************************************//**
|
||||
Acquire mutex on all buffer pool instances. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_pool_mutex_enter_all(void)
|
||||
/*==========================*/
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < srv_buf_pool_instances; i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Release mutex on all buffer pool instances. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_pool_mutex_exit_all(void)
|
||||
/*=========================*/
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < srv_buf_pool_instances; i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
@@ -31,6 +31,7 @@ Created 11/5/1995 Heikki Tuuri
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "mtr0types.h"
|
||||
#include "buf0types.h"
|
||||
#include "log0log.h"
|
||||
|
||||
/********************************************************************//**
|
||||
Remove a block from the flush list of modified blocks. */
|
||||
@@ -58,11 +59,19 @@ buf_flush_write_complete(
|
||||
buf_page_t* bpage); /*!< in: pointer to the block in question */
|
||||
/*********************************************************************//**
|
||||
Flushes pages from the end of the LRU list if there is too small
|
||||
a margin of replaceable pages there. */
|
||||
a margin of replaceable pages there. If buffer pool is NULL it
|
||||
means flush free margin on all buffer pool instances. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_free_margin(void);
|
||||
/*=======================*/
|
||||
buf_flush_free_margin(
|
||||
/*==================*/
|
||||
buf_pool_t* buf_pool);
|
||||
/*********************************************************************//**
|
||||
Flushes pages from the end of all the LRU lists. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_flush_free_margins(void);
|
||||
/*=========================*/
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/********************************************************************//**
|
||||
Initializes a page for writing to the tablespace. */
|
||||
@@ -76,21 +85,30 @@ buf_flush_init_for_writing(
|
||||
to the page */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*******************************************************************//**
|
||||
This utility flushes dirty blocks from the end of the LRU list or flush_list.
|
||||
NOTE 1: in the case of an LRU flush the calling thread may own latches to
|
||||
pages: to avoid deadlocks, this function must be written so that it cannot
|
||||
end up waiting for these latches! NOTE 2: in the case of a flush list flush,
|
||||
the calling thread is not allowed to own any latches on pages!
|
||||
This utility flushes dirty blocks from the end of the LRU list.
|
||||
NOTE: The calling thread may own latches to pages: to avoid deadlocks,
|
||||
this function must be written so that it cannot end up waiting for these
|
||||
latches!
|
||||
@return number of blocks for which the write request was queued;
|
||||
ULINT_UNDEFINED if there was a flush of the same type already running */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_flush_batch(
|
||||
buf_flush_LRU(
|
||||
/*==========*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint min_n); /*!< in: wished minimum mumber of blocks
|
||||
flushed (it is not guaranteed that the
|
||||
actual number is that big, though) */
|
||||
/*******************************************************************//**
|
||||
This utility flushes dirty blocks from the end of the flush_list of
|
||||
all buffer pool instances.
|
||||
NOTE: The calling thread is not allowed to own any latches on pages!
|
||||
@return number of blocks for which the write request was queued;
|
||||
ULINT_UNDEFINED if there was a flush of the same type already running */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_flush_list(
|
||||
/*============*/
|
||||
enum buf_flush flush_type, /*!< in: BUF_FLUSH_LRU or
|
||||
BUF_FLUSH_LIST; if BUF_FLUSH_LIST,
|
||||
then the caller must not own any
|
||||
latches on pages */
|
||||
ulint min_n, /*!< in: wished minimum mumber of blocks
|
||||
flushed (it is not guaranteed that the
|
||||
actual number is that big, though) */
|
||||
@@ -105,7 +123,9 @@ UNIV_INTERN
|
||||
void
|
||||
buf_flush_wait_batch_end(
|
||||
/*=====================*/
|
||||
enum buf_flush type); /*!< in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
enum buf_flush type); /*!< in: BUF_FLUSH_LRU
|
||||
or BUF_FLUSH_LIST */
|
||||
/********************************************************************//**
|
||||
This function should be called at a mini-transaction commit, if a page was
|
||||
modified in it. Puts the block to the list of modified blocks, if it not
|
||||
@@ -181,8 +201,9 @@ Validates the flush list.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_flush_validate(void);
|
||||
/*====================*/
|
||||
buf_flush_validate(
|
||||
/*===============*/
|
||||
buf_pool_t* buf_pool);
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
|
||||
/********************************************************************//**
|
||||
@@ -205,9 +226,10 @@ buf_flush_free_flush_rbt(void);
|
||||
available to replacement in the free list and at the end of the LRU list (to
|
||||
make sure that a read-ahead batch can be read efficiently in a single
|
||||
sweep). */
|
||||
#define BUF_FLUSH_FREE_BLOCK_MARGIN (5 + BUF_READ_AHEAD_AREA)
|
||||
#define BUF_FLUSH_FREE_BLOCK_MARGIN(b) (5 + BUF_READ_AHEAD_AREA(b))
|
||||
/** Extra margin to apply above BUF_FLUSH_FREE_BLOCK_MARGIN */
|
||||
#define BUF_FLUSH_EXTRA_MARGIN (BUF_FLUSH_FREE_BLOCK_MARGIN / 4 + 100)
|
||||
#define BUF_FLUSH_EXTRA_MARGIN(b) (BUF_FLUSH_FREE_BLOCK_MARGIN(b) / 4 \
|
||||
+ 100)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
|
@@ -33,8 +33,9 @@ UNIV_INTERN
|
||||
void
|
||||
buf_flush_insert_into_flush_list(
|
||||
/*=============================*/
|
||||
buf_block_t* block, /*!< in/out: block which is modified */
|
||||
ib_uint64_t lsn); /*!< in: oldest modification */
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
buf_block_t* block, /*!< in/out: block which is modified */
|
||||
ib_uint64_t lsn); /*!< in: oldest modification */
|
||||
/********************************************************************//**
|
||||
Inserts a modified block into the flush list in the right sorted position.
|
||||
This function is used by recovery, because there the modifications do not
|
||||
@@ -43,8 +44,9 @@ UNIV_INTERN
|
||||
void
|
||||
buf_flush_insert_sorted_into_flush_list(
|
||||
/*====================================*/
|
||||
buf_block_t* block, /*!< in/out: block which is modified */
|
||||
ib_uint64_t lsn); /*!< in: oldest modification */
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
buf_block_t* block, /*!< in/out: block which is modified */
|
||||
ib_uint64_t lsn); /*!< in: oldest modification */
|
||||
|
||||
/********************************************************************//**
|
||||
This function should be called at a mini-transaction commit, if a page was
|
||||
@@ -57,6 +59,8 @@ buf_flush_note_modification(
|
||||
buf_block_t* block, /*!< in: block which is modified */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_block(block);
|
||||
|
||||
ut_ad(block);
|
||||
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->page.buf_fix_count > 0);
|
||||
@@ -64,9 +68,9 @@ buf_flush_note_modification(
|
||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
ut_ad(!buf_pool_mutex_own());
|
||||
ut_ad(!buf_flush_list_mutex_own());
|
||||
ut_ad(buf_flush_order_mutex_own());
|
||||
ut_ad(!buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!buf_flush_list_mutex_own(buf_pool));
|
||||
ut_ad(log_flush_order_mutex_own());
|
||||
|
||||
ut_ad(mtr->start_lsn != 0);
|
||||
ut_ad(mtr->modifications);
|
||||
@@ -77,7 +81,8 @@ buf_flush_note_modification(
|
||||
block->page.newest_modification = mtr->end_lsn;
|
||||
|
||||
if (!block->page.oldest_modification) {
|
||||
buf_flush_insert_into_flush_list(block, mtr->start_lsn);
|
||||
buf_flush_insert_into_flush_list(
|
||||
buf_pool, block, mtr->start_lsn);
|
||||
} else {
|
||||
ut_ad(block->page.oldest_modification <= mtr->start_lsn);
|
||||
}
|
||||
@@ -99,6 +104,8 @@ buf_flush_recv_note_modification(
|
||||
ib_uint64_t end_lsn) /*!< in: end lsn of the last mtr in the
|
||||
set of mtr's */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_block(block);
|
||||
|
||||
ut_ad(block);
|
||||
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->page.buf_fix_count > 0);
|
||||
@@ -106,9 +113,9 @@ buf_flush_recv_note_modification(
|
||||
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
ut_ad(!buf_pool_mutex_own());
|
||||
ut_ad(!buf_flush_list_mutex_own());
|
||||
ut_ad(buf_flush_order_mutex_own());
|
||||
ut_ad(!buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(!buf_flush_list_mutex_own(buf_pool));
|
||||
ut_ad(log_flush_order_mutex_own());
|
||||
|
||||
ut_ad(start_lsn != 0);
|
||||
ut_ad(block->page.newest_modification <= end_lsn);
|
||||
@@ -117,7 +124,8 @@ buf_flush_recv_note_modification(
|
||||
block->page.newest_modification = end_lsn;
|
||||
|
||||
if (!block->page.oldest_modification) {
|
||||
buf_flush_insert_sorted_into_flush_list(block, start_lsn);
|
||||
buf_flush_insert_sorted_into_flush_list(
|
||||
buf_pool, block, start_lsn);
|
||||
} else {
|
||||
ut_ad(block->page.oldest_modification <= start_lsn);
|
||||
}
|
||||
|
@@ -52,8 +52,9 @@ operations need new buffer blocks, and the i/o work done in flushing would be
|
||||
wasted. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_try_free_flushed_blocks(void);
|
||||
/*==================================*/
|
||||
buf_LRU_try_free_flushed_blocks(
|
||||
/*============================*/
|
||||
buf_pool_t* buf_pool); /*!< in: buffer pool instance */
|
||||
/******************************************************************//**
|
||||
Returns TRUE if less than 25 % of the buffer pool is available. This can be
|
||||
used in heuristics to prevent huge transactions eating up the whole buffer
|
||||
@@ -72,7 +73,7 @@ These are low-level functions
|
||||
#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */
|
||||
|
||||
/** Maximum LRU list search length in buf_flush_LRU_recommendation() */
|
||||
#define BUF_LRU_FREE_SEARCH_LEN (5 + 2 * BUF_READ_AHEAD_AREA)
|
||||
#define BUF_LRU_FREE_SEARCH_LEN(b) (5 + 2 * BUF_READ_AHEAD_AREA(b))
|
||||
|
||||
/******************************************************************//**
|
||||
Invalidates all pages belonging to a given tablespace when we are deleting
|
||||
@@ -97,10 +98,10 @@ Try to free a block. If bpage is a descriptor of a compressed-only
|
||||
page, the descriptor object will be freed as well.
|
||||
|
||||
NOTE: If this function returns BUF_LRU_FREED, it will not temporarily
|
||||
release buf_pool_mutex. Furthermore, the page frame will no longer be
|
||||
release buf_pool->mutex. Furthermore, the page frame will no longer be
|
||||
accessible via bpage.
|
||||
|
||||
The caller must hold buf_pool_mutex and buf_page_get_mutex(bpage) and
|
||||
The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
|
||||
release these two mutexes after the call. No other
|
||||
buf_page_get_mutex() may be held when calling this function.
|
||||
@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
|
||||
@@ -114,7 +115,7 @@ buf_LRU_free_block(
|
||||
compressed page of an uncompressed page */
|
||||
ibool* buf_pool_mutex_released);
|
||||
/*!< in: pointer to a variable that will
|
||||
be assigned TRUE if buf_pool_mutex
|
||||
be assigned TRUE if buf_pool->mutex
|
||||
was temporarily released, or NULL */
|
||||
/******************************************************************//**
|
||||
Try to free a replaceable block.
|
||||
@@ -123,22 +124,26 @@ UNIV_INTERN
|
||||
ibool
|
||||
buf_LRU_search_and_free_block(
|
||||
/*==========================*/
|
||||
ulint n_iterations); /*!< in: how many times this has been called
|
||||
repeatedly without result: a high value means
|
||||
that we should search farther; if
|
||||
n_iterations < 10, then we search
|
||||
n_iterations / 10 * buf_pool->curr_size
|
||||
pages from the end of the LRU list; if
|
||||
n_iterations < 5, then we will also search
|
||||
n_iterations / 5 of the unzip_LRU list. */
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint n_iterations); /*!< in: how many times this has
|
||||
been called repeatedly without
|
||||
result: a high value means that
|
||||
we should search farther; if
|
||||
n_iterations < 10, then we search
|
||||
n_iterations / 10 * buf_pool->curr_size
|
||||
pages from the end of the LRU list; if
|
||||
n_iterations < 5, then we will
|
||||
also search n_iterations / 5
|
||||
of the unzip_LRU list. */
|
||||
/******************************************************************//**
|
||||
Returns a free block from the buf_pool. The block is taken off the
|
||||
free list. If it is empty, returns NULL.
|
||||
@return a free control block, or NULL if the buf_block->free list is empty */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_LRU_get_free_only(void);
|
||||
/*=======================*/
|
||||
buf_LRU_get_free_only(
|
||||
/*==================*/
|
||||
buf_pool_t* buf_pool); /*!< buffer pool instance */
|
||||
/******************************************************************//**
|
||||
Returns a free block from the buf_pool. The block is taken off the
|
||||
free list. If it is empty, blocks are moved from the end of the
|
||||
@@ -148,8 +153,9 @@ UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_LRU_get_free_block(
|
||||
/*===================*/
|
||||
ulint zip_size); /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
buf_pool_t* buf_pool, /*!< in: preferred buffer pool */
|
||||
ulint zip_size); /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
|
||||
/******************************************************************//**
|
||||
Puts a block back to the free list. */
|
||||
@@ -196,7 +202,7 @@ buf_LRU_make_block_old(
|
||||
Updates buf_LRU_old_ratio.
|
||||
@return updated old_pct */
|
||||
UNIV_INTERN
|
||||
uint
|
||||
ulint
|
||||
buf_LRU_old_ratio_update(
|
||||
/*=====================*/
|
||||
uint old_pct,/*!< in: Reserve this percentage of
|
||||
@@ -232,7 +238,7 @@ buf_LRU_print(void);
|
||||
|
||||
/** @name Heuristics for detecting index scan @{ */
|
||||
/** Reserve this much/BUF_LRU_OLD_RATIO_DIV of the buffer pool for
|
||||
"old" blocks. Protected by buf_pool_mutex. */
|
||||
"old" blocks. Protected by buf_pool->mutex. */
|
||||
extern uint buf_LRU_old_ratio;
|
||||
/** The denominator of buf_LRU_old_ratio. */
|
||||
#define BUF_LRU_OLD_RATIO_DIV 1024
|
||||
@@ -278,7 +284,7 @@ Cleared by buf_LRU_stat_update(). */
|
||||
extern buf_LRU_stat_t buf_LRU_stat_cur;
|
||||
|
||||
/** Running sum of past values of buf_LRU_stat_cur.
|
||||
Updated by buf_LRU_stat_update(). Protected by buf_pool_mutex. */
|
||||
Updated by buf_LRU_stat_update(). Protected by buf_pool->mutex. */
|
||||
extern buf_LRU_stat_t buf_LRU_stat_sum;
|
||||
|
||||
/********************************************************************//**
|
||||
|
@@ -124,8 +124,8 @@ buf_read_recv_pages(
|
||||
|
||||
/** The size in pages of the area which the read-ahead algorithms read if
|
||||
invoked */
|
||||
#define BUF_READ_AHEAD_AREA \
|
||||
ut_min(64, ut_2_power_up(buf_pool->curr_size / 32))
|
||||
#define BUF_READ_AHEAD_AREA(b) \
|
||||
ut_min(64, ut_2_power_up((b)->curr_size / 32))
|
||||
|
||||
/** @name Modes used in read-ahead @{ */
|
||||
/** read only pages belonging to the insert buffer tree */
|
||||
|
@@ -36,6 +36,8 @@ typedef struct buf_chunk_struct buf_chunk_t;
|
||||
typedef struct buf_pool_struct buf_pool_t;
|
||||
/** Buffer pool statistics struct */
|
||||
typedef struct buf_pool_stat_struct buf_pool_stat_t;
|
||||
/** Buffer pool buddy statistics struct */
|
||||
typedef struct buf_buddy_stat_struct buf_buddy_stat_t;
|
||||
|
||||
/** A buffer frame. @see page_t */
|
||||
typedef byte buf_frame_t;
|
||||
|
@@ -110,7 +110,7 @@ ibuf_should_try(
|
||||
|
||||
if (ibuf_flush_count % 4 == 0) {
|
||||
|
||||
buf_LRU_try_free_flushed_blocks();
|
||||
buf_LRU_try_free_flushed_blocks(NULL);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
|
@@ -763,6 +763,15 @@ struct log_struct{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
mutex_t mutex; /*!< mutex protecting the log */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
mutex_t log_flush_order_mutex;/*!< mutex to serialize access to
|
||||
the flush list when we are putting
|
||||
dirty blocks in the list. The idea
|
||||
behind this mutex is to be able
|
||||
to release log_sys->mutex during
|
||||
mtr_commit and still ensure that
|
||||
insertions in the flush_list happen
|
||||
in the LSN order. */
|
||||
byte* buf_ptr; /* unaligned log buffer */
|
||||
byte* buf; /*!< log buffer */
|
||||
ulint buf_size; /*!< log buffer size in bytes */
|
||||
@@ -952,6 +961,19 @@ struct log_struct{
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
};
|
||||
|
||||
/** Test if flush order mutex is owned. */
|
||||
#define log_flush_order_mutex_own() \
|
||||
mutex_own(&log_sys->log_flush_order_mutex)
|
||||
|
||||
/** Acquire the flush order mutex. */
|
||||
#define log_flush_order_mutex_enter() do { \
|
||||
mutex_enter(&log_sys->log_flush_order_mutex); \
|
||||
} while (0)
|
||||
/** Release the flush order mutex. */
|
||||
# define log_flush_order_mutex_exit() do { \
|
||||
mutex_exit(&log_sys->log_flush_order_mutex); \
|
||||
} while (0)
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/** Archiving state @{ */
|
||||
#define LOG_ARCH_ON 71
|
||||
|
@@ -142,6 +142,7 @@ extern my_bool srv_use_sys_malloc;
|
||||
extern ibool srv_use_sys_malloc;
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
extern ulint srv_buf_pool_size; /*!< requested size in bytes */
|
||||
extern ulint srv_buf_pool_instances; /*!< requested number of buffer pool instances */
|
||||
extern ulint srv_buf_pool_old_size; /*!< previously requested size */
|
||||
extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
|
||||
extern ulint srv_mem_pool_size;
|
||||
|
@@ -81,13 +81,13 @@ extern mysql_pfs_key_t dict_sys_mutex_key;
|
||||
extern mysql_pfs_key_t file_format_max_mutex_key;
|
||||
extern mysql_pfs_key_t fil_system_mutex_key;
|
||||
extern mysql_pfs_key_t flush_list_mutex_key;
|
||||
extern mysql_pfs_key_t flush_order_mutex_key;
|
||||
extern mysql_pfs_key_t hash_table_mutex_key;
|
||||
extern mysql_pfs_key_t ibuf_bitmap_mutex_key;
|
||||
extern mysql_pfs_key_t ibuf_mutex_key;
|
||||
extern mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key;
|
||||
extern mysql_pfs_key_t ios_mutex_key;
|
||||
extern mysql_pfs_key_t log_sys_mutex_key;
|
||||
extern mysql_pfs_key_t log_flush_order_mutex_key;
|
||||
extern mysql_pfs_key_t kernel_mutex_key;
|
||||
# ifdef UNIV_MEM_DEBUG
|
||||
extern mysql_pfs_key_t mem_hash_mutex_key;
|
||||
@@ -661,6 +661,7 @@ or row lock! */
|
||||
#define SYNC_TRX_LOCK_HEAP 298
|
||||
#define SYNC_TRX_SYS_HEADER 290
|
||||
#define SYNC_LOG 170
|
||||
#define SYNC_LOG_FLUSH_ORDER 147
|
||||
#define SYNC_RECV 168
|
||||
#define SYNC_WORK_QUEUE 162
|
||||
#define SYNC_SEARCH_SYS_CONF 161 /* for assigning btr_search_enabled */
|
||||
@@ -671,7 +672,6 @@ or row lock! */
|
||||
can call routines there! Otherwise
|
||||
the level is SYNC_MEM_HASH. */
|
||||
#define SYNC_BUF_POOL 150 /* Buffer pool mutex */
|
||||
#define SYNC_BUF_FLUSH_ORDER 147
|
||||
#define SYNC_BUF_BLOCK 146 /* Block mutex */
|
||||
#define SYNC_BUF_FLUSH_LIST 145 /* Buffer flush list mutex */
|
||||
#define SYNC_DOUBLEWRITE 140
|
||||
|
@@ -113,12 +113,13 @@ ut_test_malloc(
|
||||
ulint n); /*!< in: try to allocate this many bytes */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/**********************************************************************//**
|
||||
Frees a memory block allocated with ut_malloc. */
|
||||
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
|
||||
a nop. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ut_free(
|
||||
/*====*/
|
||||
void* ptr); /*!< in, own: memory block */
|
||||
void* ptr); /*!< in, own: memory block, can be NULL */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**********************************************************************//**
|
||||
Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not
|
||||
|
@@ -1,6 +1,29 @@
|
||||
/******************************************************
|
||||
Red-Black tree implementation.
|
||||
(c) 2007 Oracle/Innobase Oy
|
||||
/***************************************************************************//**
|
||||
|
||||
Copyright (c) 2007, 2010, Innobase Oy. All Rights Reserved.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
|
||||
are described briefly in the InnoDB documentation. The contributions by
|
||||
Sun Microsystems are incorporated with their permission, and subject to the
|
||||
conditions contained in the file COPYING.Sun_Microsystems.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*****************************************************************************/
|
||||
/******************************************************************//**
|
||||
@file include/ut0rbt.h
|
||||
Various utilities
|
||||
|
||||
Created 2007-03-20 Sunny Bains
|
||||
*******************************************************/
|
||||
@@ -35,7 +58,7 @@ typedef struct ib_rbt_bound_struct ib_rbt_bound_t;
|
||||
typedef void (*ib_rbt_print_node)(const ib_rbt_node_t* node);
|
||||
typedef int (*ib_rbt_compare)(const void* p1, const void* p2);
|
||||
|
||||
/* Red black tree color types */
|
||||
/** Red black tree color types */
|
||||
enum ib_rbt_color_enum {
|
||||
IB_RBT_RED,
|
||||
IB_RBT_BLACK
|
||||
@@ -43,7 +66,7 @@ enum ib_rbt_color_enum {
|
||||
|
||||
typedef enum ib_rbt_color_enum ib_rbt_color_t;
|
||||
|
||||
/* Red black tree node */
|
||||
/** Red black tree node */
|
||||
struct ib_rbt_node_struct {
|
||||
ib_rbt_color_t color; /* color of this node */
|
||||
|
||||
@@ -54,7 +77,7 @@ struct ib_rbt_node_struct {
|
||||
char value[1]; /* Data value */
|
||||
};
|
||||
|
||||
/* Red black tree instance.*/
|
||||
/** Red black tree instance.*/
|
||||
struct ib_rbt_struct {
|
||||
ib_rbt_node_t* nil; /* Black colored node that is
|
||||
used as a sentinel. This is
|
||||
@@ -70,7 +93,7 @@ struct ib_rbt_struct {
|
||||
ulint sizeof_value; /* Sizeof the item in bytes */
|
||||
};
|
||||
|
||||
/* The result of searching for a key in the tree, this is useful for
|
||||
/** The result of searching for a key in the tree, this is useful for
|
||||
a speedy lookup and insert if key doesn't exist.*/
|
||||
struct ib_rbt_bound_struct {
|
||||
const ib_rbt_node_t*
|
||||
@@ -93,14 +116,14 @@ struct ib_rbt_bound_struct {
|
||||
/* Compare a key with the node value (t is tree, k is key, n is node)*/
|
||||
#define rbt_compare(t, k, n) (t->compare(k, n->value))
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Free an instance of a red black tree */
|
||||
UNIV_INTERN
|
||||
void
|
||||
rbt_free(
|
||||
/*=====*/
|
||||
ib_rbt_t* tree); /*!< in: rb tree to free */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Create an instance of a red black tree
|
||||
@return rb tree instance */
|
||||
UNIV_INTERN
|
||||
@@ -109,7 +132,7 @@ rbt_create(
|
||||
/*=======*/
|
||||
size_t sizeof_value, /*!< in: size in bytes */
|
||||
ib_rbt_compare compare); /*!< in: comparator */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Delete a node from the red black tree, identified by key */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
@@ -118,7 +141,7 @@ rbt_delete(
|
||||
/* in: TRUE on success */
|
||||
ib_rbt_t* tree, /* in: rb tree */
|
||||
const void* key); /* in: key to delete */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Remove a node from the red black tree, NOTE: This function will not delete
|
||||
the node instance, THAT IS THE CALLERS RESPONSIBILITY.
|
||||
@return the deleted node with the const. */
|
||||
@@ -132,7 +155,7 @@ rbt_remove_node(
|
||||
is a fudge and declared const
|
||||
because the caller has access
|
||||
only to const nodes.*/
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return a node from the red black tree, identified by
|
||||
key, NULL if not found
|
||||
@return node if found else return NULL */
|
||||
@@ -142,7 +165,7 @@ rbt_lookup(
|
||||
/*=======*/
|
||||
const ib_rbt_t* tree, /*!< in: rb tree to search */
|
||||
const void* key); /*!< in: key to lookup */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Add data to the red black tree, identified by key (no dups yet!)
|
||||
@return inserted node */
|
||||
UNIV_INTERN
|
||||
@@ -153,7 +176,7 @@ rbt_insert(
|
||||
const void* key, /*!< in: key for ordering */
|
||||
const void* value); /*!< in: data that will be
|
||||
copied to the node.*/
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Add a new node to the tree, useful for data that is pre-sorted.
|
||||
@return appended node */
|
||||
UNIV_INTERN
|
||||
@@ -164,7 +187,7 @@ rbt_add_node(
|
||||
ib_rbt_bound_t* parent, /*!< in: parent */
|
||||
const void* value); /*!< in: this value is copied
|
||||
to the node */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the left most data node in the tree
|
||||
@return left most node */
|
||||
UNIV_INTERN
|
||||
@@ -172,7 +195,7 @@ const ib_rbt_node_t*
|
||||
rbt_first(
|
||||
/*======*/
|
||||
const ib_rbt_t* tree); /*!< in: rb tree */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the right most data node in the tree
|
||||
@return right most node */
|
||||
UNIV_INTERN
|
||||
@@ -180,7 +203,7 @@ const ib_rbt_node_t*
|
||||
rbt_last(
|
||||
/*=====*/
|
||||
const ib_rbt_t* tree); /*!< in: rb tree */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the next node from current.
|
||||
@return successor node to current that is passed in. */
|
||||
UNIV_INTERN
|
||||
@@ -190,7 +213,7 @@ rbt_next(
|
||||
const ib_rbt_t* tree, /*!< in: rb tree */
|
||||
const ib_rbt_node_t* /* in: current node */
|
||||
current);
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the prev node from current.
|
||||
@return precedessor node to current that is passed in */
|
||||
UNIV_INTERN
|
||||
@@ -200,7 +223,7 @@ rbt_prev(
|
||||
const ib_rbt_t* tree, /*!< in: rb tree */
|
||||
const ib_rbt_node_t* /* in: current node */
|
||||
current);
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the node that has the lowest key that is >= key.
|
||||
@return node that satisfies the lower bound constraint or NULL */
|
||||
UNIV_INTERN
|
||||
@@ -209,7 +232,7 @@ rbt_lower_bound(
|
||||
/*============*/
|
||||
const ib_rbt_t* tree, /*!< in: rb tree */
|
||||
const void* key); /*!< in: key to search */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the node that has the greatest key that is <= key.
|
||||
@return node that satisifies the upper bound constraint or NULL */
|
||||
UNIV_INTERN
|
||||
@@ -218,7 +241,7 @@ rbt_upper_bound(
|
||||
/*============*/
|
||||
const ib_rbt_t* tree, /*!< in: rb tree */
|
||||
const void* key); /*!< in: key to search */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Search for the key, a node will be retuned in parent.last, whether it
|
||||
was found or not. If not found then parent.last will contain the
|
||||
parent node for the possibly new key otherwise the matching node.
|
||||
@@ -230,7 +253,7 @@ rbt_search(
|
||||
const ib_rbt_t* tree, /*!< in: rb tree */
|
||||
ib_rbt_bound_t* parent, /*!< in: search bounds */
|
||||
const void* key); /*!< in: key to search */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Search for the key, a node will be retuned in parent.last, whether it
|
||||
was found or not. If not found then parent.last will contain the
|
||||
parent node for the possibly new key otherwise the matching node.
|
||||
@@ -243,14 +266,14 @@ rbt_search_cmp(
|
||||
ib_rbt_bound_t* parent, /*!< in: search bounds */
|
||||
const void* key, /*!< in: key to search */
|
||||
ib_rbt_compare compare); /*!< in: comparator */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Clear the tree, deletes (and free's) all the nodes. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
rbt_clear(
|
||||
/*======*/
|
||||
ib_rbt_t* tree); /*!< in: rb tree */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Merge the node from dst into src. Return the number of nodes merged.
|
||||
@return no. of recs merged */
|
||||
UNIV_INTERN
|
||||
@@ -259,7 +282,7 @@ rbt_merge_uniq(
|
||||
/*===========*/
|
||||
ib_rbt_t* dst, /*!< in: dst rb tree */
|
||||
const ib_rbt_t* src); /*!< in: src rb tree */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Merge the node from dst into src. Return the number of nodes merged.
|
||||
Delete the nodes from src after copying node to dst. As a side effect
|
||||
the duplicates will be left untouched in the src, since we don't support
|
||||
@@ -272,7 +295,7 @@ rbt_merge_uniq_destructive(
|
||||
/*=======================*/
|
||||
ib_rbt_t* dst, /*!< in: dst rb tree */
|
||||
ib_rbt_t* src); /*!< in: src rb tree */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Verify the integrity of the RB tree. For debugging. 0 failure else height
|
||||
of tree (in count of black nodes).
|
||||
@return TRUE if OK FALSE if tree invalid. */
|
||||
@@ -281,7 +304,7 @@ ibool
|
||||
rbt_validate(
|
||||
/*=========*/
|
||||
const ib_rbt_t* tree); /*!< in: tree to validate */
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Iterate over the tree in depth first order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
|
@@ -91,6 +91,7 @@ UNIV_INTERN mysql_pfs_key_t archive_lock_key;
|
||||
|
||||
#ifdef UNIV_PFS_MUTEX
|
||||
UNIV_INTERN mysql_pfs_key_t log_sys_mutex_key;
|
||||
UNIV_INTERN mysql_pfs_key_t log_flush_order_mutex_key;
|
||||
#endif /* UNIV_PFS_MUTEX */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
@@ -769,6 +770,10 @@ log_init(void)
|
||||
|
||||
mutex_create(log_sys_mutex_key, &log_sys->mutex, SYNC_LOG);
|
||||
|
||||
mutex_create(log_flush_order_mutex_key,
|
||||
&log_sys->log_flush_order_mutex,
|
||||
SYNC_LOG_FLUSH_ORDER);
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
/* Start the lsn from one log block from zero: this way every
|
||||
@@ -1650,10 +1655,10 @@ log_preflush_pool_modified_pages(
|
||||
recv_apply_hashed_log_recs(TRUE);
|
||||
}
|
||||
|
||||
n_pages = buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX, new_oldest);
|
||||
n_pages = buf_flush_list(ULINT_MAX, new_oldest);
|
||||
|
||||
if (sync) {
|
||||
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
|
||||
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
|
||||
}
|
||||
|
||||
if (n_pages == ULINT_UNDEFINED) {
|
||||
@@ -3285,9 +3290,9 @@ log_check_log_recs(
|
||||
|
||||
ut_memcpy(scan_buf, start, end - start);
|
||||
|
||||
recv_scan_log_recs((buf_pool->curr_size
|
||||
- recv_n_pool_free_frames) * UNIV_PAGE_SIZE,
|
||||
FALSE, scan_buf, end - start,
|
||||
recv_scan_log_recs((buf_pool_get_n_pages()
|
||||
- (recv_n_pool_free_frames * srv_buf_pool_instances))
|
||||
* UNIV_PAGE_SIZE, FALSE, scan_buf, end - start,
|
||||
ut_uint64_align_down(buf_start_lsn,
|
||||
OS_FILE_LOG_BLOCK_SIZE),
|
||||
&contiguous_lsn, &scanned_lsn);
|
||||
|
@@ -1659,11 +1659,15 @@ recv_recover_page_func(
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (modification_to_page) {
|
||||
buf_pool_t* buf_pool;
|
||||
|
||||
ut_a(block);
|
||||
|
||||
buf_flush_order_mutex_enter();
|
||||
buf_pool = buf_pool_from_block(block);
|
||||
|
||||
log_flush_order_mutex_enter();
|
||||
buf_flush_recv_note_modification(block, start_lsn, end_lsn);
|
||||
buf_flush_order_mutex_exit();
|
||||
log_flush_order_mutex_exit();
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
@@ -1848,11 +1852,10 @@ loop:
|
||||
mutex_exit(&(recv_sys->mutex));
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
|
||||
n_pages = buf_flush_batch(BUF_FLUSH_LIST, ULINT_MAX,
|
||||
IB_ULONGLONG_MAX);
|
||||
ut_a(n_pages != ULINT_UNDEFINED);
|
||||
|
||||
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
|
||||
n_pages = buf_flush_list(ULINT_MAX, IB_ULONGLONG_MAX);
|
||||
ut_a(n_pages != ULINT_UNDEFINED);
|
||||
|
||||
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
|
||||
|
||||
buf_pool_invalidate();
|
||||
|
||||
@@ -2762,8 +2765,8 @@ recv_scan_log_recs(
|
||||
recv_parse_log_recs(store_to_hash);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (store_to_hash && mem_heap_get_size(recv_sys->heap)
|
||||
> available_memory) {
|
||||
if (store_to_hash
|
||||
&& mem_heap_get_size(recv_sys->heap) > available_memory) {
|
||||
|
||||
/* Hash table of log records has grown too big:
|
||||
empty it; FALSE means no ibuf operations
|
||||
@@ -2815,8 +2818,10 @@ recv_group_scan_log_recs(
|
||||
group, start_lsn, end_lsn);
|
||||
|
||||
finished = recv_scan_log_recs(
|
||||
(buf_pool->curr_size - recv_n_pool_free_frames)
|
||||
* UNIV_PAGE_SIZE, TRUE, log_sys->buf, RECV_SCAN_SIZE,
|
||||
(buf_pool_get_n_pages()
|
||||
- (recv_n_pool_free_frames * srv_buf_pool_instances))
|
||||
* UNIV_PAGE_SIZE,
|
||||
TRUE, log_sys->buf, RECV_SCAN_SIZE,
|
||||
start_lsn, contiguous_lsn, group_scanned_lsn);
|
||||
start_lsn = end_lsn;
|
||||
}
|
||||
@@ -3497,6 +3502,7 @@ recv_reset_log_files_for_backup(
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
/* Dead code */
|
||||
/******************************************************//**
|
||||
Reads from the archive of a log group and performs recovery.
|
||||
@return TRUE if no more complete consistent archive files */
|
||||
@@ -3662,7 +3668,8 @@ ask_again:
|
||||
read_offset % UNIV_PAGE_SIZE, len, buf, NULL);
|
||||
|
||||
ret = recv_scan_log_recs(
|
||||
(buf_pool->n_frames - recv_n_pool_free_frames)
|
||||
(buf_pool_get_n_pages()
|
||||
- (recv_n_pool_free_frames * srv_buf_pool_instances))
|
||||
* UNIV_PAGE_SIZE, TRUE, buf, len, start_lsn,
|
||||
&dummy_lsn, &scanned_lsn);
|
||||
|
||||
|
@@ -347,7 +347,7 @@ mem_heap_create_block(
|
||||
return(NULL);
|
||||
}
|
||||
} else {
|
||||
buf_block = buf_block_alloc(0);
|
||||
buf_block = buf_block_alloc(NULL, 0);
|
||||
}
|
||||
|
||||
block = (mem_block_t*) buf_block->frame;
|
||||
|
@@ -120,10 +120,14 @@ mtr_memo_slot_note_modification(
|
||||
ut_ad(mtr);
|
||||
ut_ad(mtr->magic_n == MTR_MAGIC_N);
|
||||
ut_ad(mtr->modifications);
|
||||
ut_ad(buf_flush_order_mutex_own());
|
||||
|
||||
if (slot->object != NULL && slot->type == MTR_MEMO_PAGE_X_FIX) {
|
||||
buf_flush_note_modification((buf_block_t*) slot->object, mtr);
|
||||
buf_block_t* block = (buf_block_t*) slot->object;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
ut_ad(log_flush_order_mutex_own());
|
||||
#endif /* UNIV_DEBUG */
|
||||
buf_flush_note_modification(block, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,16 +225,18 @@ mtr_log_reserve_and_write(
|
||||
mtr->end_lsn = log_close();
|
||||
|
||||
func_exit:
|
||||
buf_flush_order_mutex_enter();
|
||||
log_flush_order_mutex_enter();
|
||||
|
||||
/* It is now safe to release the log mutex because the
|
||||
flush_order mutex will ensure that we are the first one
|
||||
to insert into the flush list. */
|
||||
log_release();
|
||||
|
||||
if (mtr->modifications) {
|
||||
mtr_memo_note_modifications(mtr);
|
||||
}
|
||||
buf_flush_order_mutex_exit();
|
||||
|
||||
log_flush_order_mutex_exit();
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
@@ -324,7 +330,7 @@ mtr_memo_release(
|
||||
|
||||
offset = dyn_array_get_data_size(memo);
|
||||
|
||||
buf_flush_order_mutex_enter();
|
||||
log_flush_order_mutex_enter();
|
||||
while (offset > 0) {
|
||||
offset -= sizeof(mtr_memo_slot_t);
|
||||
|
||||
@@ -340,7 +346,7 @@ mtr_memo_release(
|
||||
break;
|
||||
}
|
||||
}
|
||||
buf_flush_order_mutex_exit();
|
||||
log_flush_order_mutex_exit();
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
@@ -4416,6 +4416,7 @@ page_zip_reorganize(
|
||||
dict_index_t* index, /*!< in: index of the B-tree node */
|
||||
mtr_t* mtr) /*!< in: mini-transaction */
|
||||
{
|
||||
buf_pool_t* buf_pool = buf_pool_from_block(block);
|
||||
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
|
||||
page_t* page = buf_block_get_frame(block);
|
||||
buf_block_t* temp_block;
|
||||
@@ -4433,7 +4434,7 @@ page_zip_reorganize(
|
||||
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
temp_block = buf_block_alloc(0);
|
||||
temp_block = buf_block_alloc(buf_pool, 0);
|
||||
btr_search_drop_page_hash_index(block);
|
||||
block->check_index_page_at_flush = TRUE;
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
|
@@ -195,6 +195,8 @@ UNIV_INTERN const byte* srv_latin1_ordering;
|
||||
UNIV_INTERN my_bool srv_use_sys_malloc = TRUE;
|
||||
/* requested size in kilobytes */
|
||||
UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
|
||||
/* requested number of buffer pool instances */
|
||||
UNIV_INTERN ulint srv_buf_pool_instances = 1;
|
||||
/* previously requested size */
|
||||
UNIV_INTERN ulint srv_buf_pool_old_size;
|
||||
/* current size in kilobytes */
|
||||
@@ -1700,7 +1702,7 @@ srv_refresh_innodb_monitor_stats(void)
|
||||
|
||||
log_refresh_stats();
|
||||
|
||||
buf_refresh_io_stats();
|
||||
buf_refresh_io_stats_all();
|
||||
|
||||
srv_n_rows_inserted_old = srv_n_rows_inserted;
|
||||
srv_n_rows_updated_old = srv_n_rows_updated;
|
||||
@@ -1911,6 +1913,14 @@ void
|
||||
srv_export_innodb_status(void)
|
||||
/*==========================*/
|
||||
{
|
||||
buf_pool_stat_t stat;
|
||||
ulint LRU_len;
|
||||
ulint free_len;
|
||||
ulint flush_list_len;
|
||||
|
||||
buf_get_total_stat(&stat);
|
||||
buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len);
|
||||
|
||||
mutex_enter(&srv_innodb_monitor_mutex);
|
||||
|
||||
export_vars.innodb_data_pending_reads
|
||||
@@ -1925,31 +1935,26 @@ srv_export_innodb_status(void)
|
||||
export_vars.innodb_data_reads = os_n_file_reads;
|
||||
export_vars.innodb_data_writes = os_n_file_writes;
|
||||
export_vars.innodb_data_written = srv_data_written;
|
||||
export_vars.innodb_buffer_pool_read_requests = buf_pool->stat.n_page_gets;
|
||||
export_vars.innodb_buffer_pool_read_requests = stat.n_page_gets;
|
||||
export_vars.innodb_buffer_pool_write_requests
|
||||
= srv_buf_pool_write_requests;
|
||||
export_vars.innodb_buffer_pool_wait_free = srv_buf_pool_wait_free;
|
||||
export_vars.innodb_buffer_pool_pages_flushed = srv_buf_pool_flushed;
|
||||
export_vars.innodb_buffer_pool_reads = srv_buf_pool_reads;
|
||||
export_vars.innodb_buffer_pool_read_ahead
|
||||
= buf_pool->stat.n_ra_pages_read;
|
||||
= stat.n_ra_pages_read;
|
||||
export_vars.innodb_buffer_pool_read_ahead_evicted
|
||||
= buf_pool->stat.n_ra_pages_evicted;
|
||||
export_vars.innodb_buffer_pool_pages_data
|
||||
= UT_LIST_GET_LEN(buf_pool->LRU);
|
||||
export_vars.innodb_buffer_pool_pages_dirty
|
||||
= UT_LIST_GET_LEN(buf_pool->flush_list);
|
||||
export_vars.innodb_buffer_pool_pages_free
|
||||
= UT_LIST_GET_LEN(buf_pool->free);
|
||||
= stat.n_ra_pages_evicted;
|
||||
export_vars.innodb_buffer_pool_pages_data = LRU_len;
|
||||
export_vars.innodb_buffer_pool_pages_dirty = flush_list_len;
|
||||
export_vars.innodb_buffer_pool_pages_free = free_len;
|
||||
#ifdef UNIV_DEBUG
|
||||
export_vars.innodb_buffer_pool_pages_latched
|
||||
= buf_get_latched_pages_number();
|
||||
#endif /* UNIV_DEBUG */
|
||||
export_vars.innodb_buffer_pool_pages_total = buf_pool->curr_size;
|
||||
export_vars.innodb_buffer_pool_pages_total = buf_pool_get_curr_size();
|
||||
|
||||
export_vars.innodb_buffer_pool_pages_misc = buf_pool->curr_size
|
||||
- UT_LIST_GET_LEN(buf_pool->LRU)
|
||||
- UT_LIST_GET_LEN(buf_pool->free);
|
||||
export_vars.innodb_buffer_pool_pages_misc = buf_pool_get_curr_size();
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
export_vars.innodb_have_atomic_builtins = 1;
|
||||
#else
|
||||
@@ -1965,9 +1970,9 @@ srv_export_innodb_status(void)
|
||||
export_vars.innodb_log_writes = srv_log_writes;
|
||||
export_vars.innodb_dblwr_pages_written = srv_dblwr_pages_written;
|
||||
export_vars.innodb_dblwr_writes = srv_dblwr_writes;
|
||||
export_vars.innodb_pages_created = buf_pool->stat.n_pages_created;
|
||||
export_vars.innodb_pages_read = buf_pool->stat.n_pages_read;
|
||||
export_vars.innodb_pages_written = buf_pool->stat.n_pages_written;
|
||||
export_vars.innodb_pages_created = stat.n_pages_created;
|
||||
export_vars.innodb_pages_read = stat.n_pages_read;
|
||||
export_vars.innodb_pages_written = stat.n_pages_written;
|
||||
export_vars.innodb_row_lock_waits = srv_n_lock_wait_count;
|
||||
export_vars.innodb_row_lock_current_waits
|
||||
= srv_n_lock_wait_current_count;
|
||||
@@ -2279,7 +2284,7 @@ srv_error_monitor_thread(
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_PFS_THREAD
|
||||
pfs_register_thread(srv_error_monitor_thread_key);
|
||||
pfs_register_thread(srv_error_monitor_thread_key);
|
||||
#endif
|
||||
|
||||
loop:
|
||||
@@ -2503,6 +2508,7 @@ srv_master_thread(
|
||||
/*!< in: a dummy parameter required by
|
||||
os_thread_create */
|
||||
{
|
||||
buf_pool_stat_t buf_stat;
|
||||
os_event_t event;
|
||||
ulint old_activity_count;
|
||||
ulint n_pages_purged = 0;
|
||||
@@ -2544,8 +2550,9 @@ loop:
|
||||
|
||||
srv_main_thread_op_info = "reserving kernel mutex";
|
||||
|
||||
n_ios_very_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
buf_get_total_stat(&buf_stat);
|
||||
n_ios_very_old = log_sys->n_log_ios + buf_stat.n_pages_read
|
||||
+ buf_stat.n_pages_written;
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
/* Store the user activity counter at the start of this loop */
|
||||
@@ -2566,8 +2573,12 @@ loop:
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
ulint cur_time = ut_time_ms();
|
||||
n_ios_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
|
||||
buf_get_total_stat(&buf_stat);
|
||||
|
||||
n_ios_old = log_sys->n_log_ios + buf_stat.n_pages_read
|
||||
+ buf_stat.n_pages_written;
|
||||
|
||||
srv_main_thread_op_info = "sleeping";
|
||||
srv_main_1_second_loops++;
|
||||
|
||||
@@ -2607,13 +2618,14 @@ loop:
|
||||
log_free_check();
|
||||
|
||||
/* If i/os during one second sleep were less than 5% of
|
||||
capacity, we assume that there is free disk i/o capacity
|
||||
available, and it makes sense to do an insert buffer merge. */
|
||||
capacity, we assume that there is free disk i/o capacity
|
||||
available, and it makes sense to do an insert buffer merge. */
|
||||
|
||||
buf_get_total_stat(&buf_stat);
|
||||
n_pend_ios = buf_get_n_pending_ios()
|
||||
+ log_sys->n_pending_writes;
|
||||
n_ios = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
|
||||
+ buf_stat.n_pages_written;
|
||||
if (n_pend_ios < SRV_PEND_IO_THRESHOLD
|
||||
&& (n_ios - n_ios_old < SRV_RECENT_IO_ACTIVITY)) {
|
||||
srv_main_thread_op_info = "doing insert buffer merge";
|
||||
@@ -2631,9 +2643,8 @@ loop:
|
||||
|
||||
srv_main_thread_op_info =
|
||||
"flushing buffer pool pages";
|
||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST,
|
||||
PCT_IO(100),
|
||||
IB_ULONGLONG_MAX);
|
||||
n_pages_flushed = buf_flush_list(
|
||||
PCT_IO(100), IB_ULONGLONG_MAX);
|
||||
|
||||
} else if (srv_adaptive_flushing) {
|
||||
|
||||
@@ -2647,8 +2658,7 @@ loop:
|
||||
"flushing buffer pool pages";
|
||||
n_flush = ut_min(PCT_IO(100), n_flush);
|
||||
n_pages_flushed =
|
||||
buf_flush_batch(
|
||||
BUF_FLUSH_LIST,
|
||||
buf_flush_list(
|
||||
n_flush,
|
||||
IB_ULONGLONG_MAX);
|
||||
}
|
||||
@@ -2680,17 +2690,17 @@ loop:
|
||||
loop above requests writes for that case. The writes done here
|
||||
are not required, and may be disabled. */
|
||||
|
||||
buf_get_total_stat(&buf_stat);
|
||||
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
|
||||
n_ios = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
n_ios = log_sys->n_log_ios + buf_stat.n_pages_read
|
||||
+ buf_stat.n_pages_written;
|
||||
|
||||
srv_main_10_second_loops++;
|
||||
if (n_pend_ios < SRV_PEND_IO_THRESHOLD
|
||||
&& (n_ios - n_ios_very_old < SRV_PAST_IO_ACTIVITY)) {
|
||||
|
||||
srv_main_thread_op_info = "flushing buffer pool pages";
|
||||
buf_flush_batch(BUF_FLUSH_LIST, PCT_IO(100),
|
||||
IB_ULONGLONG_MAX);
|
||||
buf_flush_list(PCT_IO(100), IB_ULONGLONG_MAX);
|
||||
|
||||
/* Flush logs if needed */
|
||||
srv_sync_log_buffer_in_background();
|
||||
@@ -2705,8 +2715,6 @@ loop:
|
||||
/* Flush logs if needed */
|
||||
srv_sync_log_buffer_in_background();
|
||||
|
||||
/* We run a full purge every 10 seconds, even if the server
|
||||
were active */
|
||||
if (srv_n_purge_threads == 0) {
|
||||
srv_main_thread_op_info = "master purging";
|
||||
|
||||
@@ -2728,17 +2736,15 @@ loop:
|
||||
(> 70 %), we assume we can afford reserving the disk(s) for
|
||||
the time it requires to flush 100 pages */
|
||||
|
||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST,
|
||||
PCT_IO(100),
|
||||
IB_ULONGLONG_MAX);
|
||||
n_pages_flushed = buf_flush_list(
|
||||
PCT_IO(100), IB_ULONGLONG_MAX);
|
||||
} else {
|
||||
/* Otherwise, we only flush a small number of pages so that
|
||||
we do not unnecessarily use much disk i/o capacity from
|
||||
other work */
|
||||
|
||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST,
|
||||
PCT_IO(10),
|
||||
IB_ULONGLONG_MAX);
|
||||
n_pages_flushed = buf_flush_list(
|
||||
PCT_IO(10), IB_ULONGLONG_MAX);
|
||||
}
|
||||
|
||||
srv_main_thread_op_info = "making checkpoint";
|
||||
@@ -2807,7 +2813,7 @@ background_loop:
|
||||
} else {
|
||||
/* This should do an amount of IO similar to the number of
|
||||
dirty pages that will be flushed in the call to
|
||||
buf_flush_batch below. Otherwise, the system favors
|
||||
buf_flush_list below. Otherwise, the system favors
|
||||
clean pages over cleanup throughput. */
|
||||
n_bytes_merged = ibuf_contract_for_n_pages(FALSE,
|
||||
PCT_IO(100));
|
||||
@@ -2826,9 +2832,8 @@ flush_loop:
|
||||
srv_main_thread_op_info = "flushing buffer pool pages";
|
||||
srv_main_flush_loops++;
|
||||
if (srv_fast_shutdown < 2) {
|
||||
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST,
|
||||
PCT_IO(100),
|
||||
IB_ULONGLONG_MAX);
|
||||
n_pages_flushed = buf_flush_list(
|
||||
PCT_IO(100), IB_ULONGLONG_MAX);
|
||||
} else {
|
||||
/* In the fastest shutdown we do not flush the buffer pool
|
||||
to data files: we set n_pages_flushed to 0 artificially. */
|
||||
@@ -2846,7 +2851,7 @@ flush_loop:
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
srv_main_thread_op_info = "waiting for buffer pool flush to end";
|
||||
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
|
||||
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
|
||||
|
||||
/* Flush logs if needed */
|
||||
srv_sync_log_buffer_in_background();
|
||||
|
@@ -1016,7 +1016,6 @@ int
|
||||
innobase_start_or_create_for_mysql(void)
|
||||
/*====================================*/
|
||||
{
|
||||
buf_pool_t* ret;
|
||||
ibool create_new_db;
|
||||
ibool log_file_created;
|
||||
ibool log_created = FALSE;
|
||||
@@ -1241,13 +1240,16 @@ innobase_start_or_create_for_mysql(void)
|
||||
#else
|
||||
if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
|
||||
/* If buffer pool is less than 1000 MB,
|
||||
assume fewer threads. */
|
||||
assume fewer threads. Also use only one
|
||||
buffer pool instance */
|
||||
srv_max_n_threads = 50000;
|
||||
|
||||
} else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
|
||||
|
||||
srv_buf_pool_instances = 1;
|
||||
srv_max_n_threads = 10000;
|
||||
} else {
|
||||
srv_buf_pool_instances = 1;
|
||||
srv_max_n_threads = 1000; /* saves several MB of memory,
|
||||
especially in 64-bit
|
||||
computers */
|
||||
@@ -1331,9 +1333,9 @@ innobase_start_or_create_for_mysql(void)
|
||||
fil_init(srv_file_per_table ? 50000 : 5000,
|
||||
srv_max_n_open_files);
|
||||
|
||||
ret = buf_pool_init();
|
||||
err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
|
||||
|
||||
if (ret == NULL) {
|
||||
if (err != DB_SUCCESS) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Fatal error: cannot allocate the memory"
|
||||
" for the buffer pool\n");
|
||||
@@ -2089,7 +2091,7 @@ innobase_shutdown_for_mysql(void)
|
||||
|
||||
pars_lexer_close();
|
||||
log_mem_free();
|
||||
buf_pool_free();
|
||||
buf_pool_free(srv_buf_pool_instances);
|
||||
ut_free_all_mem();
|
||||
mem_close();
|
||||
|
||||
|
@@ -1157,14 +1157,12 @@ sync_thread_add_level(
|
||||
case SYNC_RECV:
|
||||
case SYNC_WORK_QUEUE:
|
||||
case SYNC_LOG:
|
||||
case SYNC_LOG_FLUSH_ORDER:
|
||||
case SYNC_THR_LOCAL:
|
||||
case SYNC_ANY_LATCH:
|
||||
case SYNC_TRX_SYS_HEADER:
|
||||
case SYNC_FILE_FORMAT_TAG:
|
||||
case SYNC_DOUBLEWRITE:
|
||||
case SYNC_BUF_FLUSH_LIST:
|
||||
case SYNC_BUF_FLUSH_ORDER:
|
||||
case SYNC_BUF_POOL:
|
||||
case SYNC_SEARCH_SYS:
|
||||
case SYNC_SEARCH_SYS_CONF:
|
||||
case SYNC_TRX_LOCK_HEAP:
|
||||
@@ -1186,6 +1184,18 @@ sync_thread_add_level(
|
||||
ut_error;
|
||||
}
|
||||
break;
|
||||
case SYNC_BUF_FLUSH_LIST:
|
||||
case SYNC_BUF_POOL:
|
||||
/* We can have multiple mutexes of this type therefore we
|
||||
can only check whether the greater than condition holds. */
|
||||
if (!sync_thread_levels_g(array, level-1, TRUE)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: sync_thread_levels_g(array, %lu)"
|
||||
" does not hold!\n", level-1);
|
||||
ut_error;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYNC_BUF_BLOCK:
|
||||
/* Either the thread must own the buffer pool mutex
|
||||
(buf_pool_mutex), or it is allowed to latch only ONE
|
||||
|
@@ -764,7 +764,6 @@ trx_commit_off_kernel(
|
||||
if (undo) {
|
||||
mutex_enter(&kernel_mutex);
|
||||
trx->no = trx_sys_get_new_trx_no();
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
/* It is not necessary to obtain trx->undo_mutex here
|
||||
|
@@ -1938,7 +1938,8 @@ trx_undo_update_cleanup(
|
||||
|
||||
UT_LIST_ADD_FIRST(undo_list, rseg->update_undo_cached, undo);
|
||||
} else {
|
||||
ut_ad(undo->state == TRX_UNDO_TO_PURGE);
|
||||
ut_ad(undo->state == TRX_UNDO_TO_PURGE
|
||||
|| undo->state == TRX_UNDO_TO_FREE);
|
||||
|
||||
trx_undo_mem_free(undo);
|
||||
}
|
||||
|
@@ -290,17 +290,20 @@ ut_test_malloc(
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/**********************************************************************//**
|
||||
Frees a memory block allocated with ut_malloc. */
|
||||
Frees a memory block allocated with ut_malloc. Freeing a NULL pointer is
|
||||
a nop. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ut_free(
|
||||
/*====*/
|
||||
void* ptr) /*!< in, own: memory block */
|
||||
void* ptr) /*!< in, own: memory block, can be NULL */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ut_mem_block_t* block;
|
||||
|
||||
if (UNIV_LIKELY(srv_use_sys_malloc)) {
|
||||
if (ptr == NULL) {
|
||||
return;
|
||||
} else if (UNIV_LIKELY(srv_use_sys_malloc)) {
|
||||
free(ptr);
|
||||
return;
|
||||
}
|
||||
|
@@ -1,4 +1,27 @@
|
||||
/**********************************************************************
|
||||
/***************************************************************************//**
|
||||
|
||||
Copyright (c) 2007, 2010, Innobase Oy. All Rights Reserved.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
|
||||
are described briefly in the InnoDB documentation. The contributions by
|
||||
Sun Microsystems are incorporated with their permission, and subject to the
|
||||
conditions contained in the file COPYING.Sun_Microsystems.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
*****************************************************************************/
|
||||
/********************************************************************//**
|
||||
Red-Black tree implementation
|
||||
|
||||
(c) 2007 Oracle/Innobase Oy
|
||||
@@ -8,7 +31,7 @@ Created 2007-03-20 Sunny Bains
|
||||
|
||||
#include "ut0rbt.h"
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Definition of a red-black tree
|
||||
==============================
|
||||
|
||||
@@ -34,7 +57,7 @@ red-black properties:
|
||||
#define ROOT(t) (t->root->left)
|
||||
#define SIZEOF_NODE(t) ((sizeof(ib_rbt_node_t) + t->sizeof_value) - 1)
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Print out the sub-tree recursively. */
|
||||
static
|
||||
void
|
||||
@@ -52,7 +75,7 @@ rbt_print_subtree(
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Verify that the keys are in order.
|
||||
@return TRUE of OK. FALSE if not ordered */
|
||||
static
|
||||
@@ -77,7 +100,7 @@ rbt_check_ordering(
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Check that every path from the root to the leaves has the same count.
|
||||
Count is expressed in the number of black nodes.
|
||||
@return 0 on failure else black height of the subtree */
|
||||
@@ -125,7 +148,7 @@ rbt_count_black_nodes(
|
||||
return(result);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Turn the node's right child's left sub-tree into node's right sub-tree.
|
||||
This will also make node's right child it's parent. */
|
||||
static
|
||||
@@ -161,7 +184,7 @@ rbt_rotate_left(
|
||||
node->parent = right;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Turn the node's left child's right sub-tree into node's left sub-tree.
|
||||
This also make node's left child it's parent. */
|
||||
static
|
||||
@@ -197,7 +220,7 @@ rbt_rotate_right(
|
||||
node->parent = left;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Append a node to the tree. */
|
||||
static
|
||||
ib_rbt_node_t*
|
||||
@@ -224,7 +247,7 @@ rbt_tree_add_child(
|
||||
return(node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Generic binary tree insert */
|
||||
static
|
||||
ib_rbt_node_t*
|
||||
@@ -260,7 +283,7 @@ rbt_tree_insert(
|
||||
return(node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Balance a tree after inserting a node. */
|
||||
static
|
||||
void
|
||||
@@ -350,7 +373,7 @@ rbt_balance_tree(
|
||||
ROOT(tree)->color = IB_RBT_BLACK;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the given node's successor.
|
||||
@return successor node or NULL if no successor */
|
||||
static
|
||||
@@ -390,7 +413,7 @@ rbt_find_successor(
|
||||
return(next);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the given node's precedecessor.
|
||||
@return predecessor node or NULL if no predecesor */
|
||||
static
|
||||
@@ -430,7 +453,7 @@ rbt_find_predecessor(
|
||||
return(prev);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Replace node with child. After applying transformations eject becomes
|
||||
an orphan. */
|
||||
static
|
||||
@@ -454,7 +477,7 @@ rbt_eject_node(
|
||||
node->parent = eject->parent;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Replace a node with another node. */
|
||||
static
|
||||
void
|
||||
@@ -481,7 +504,7 @@ rbt_replace_node(
|
||||
replace->color = color;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Detach node from the tree replacing it with one of it's children.
|
||||
@return the child node that now occupies the position of the detached node */
|
||||
static
|
||||
@@ -524,7 +547,7 @@ rbt_detach_node(
|
||||
return(child);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Rebalance the right sub-tree after deletion.
|
||||
@return node to rebalance if more rebalancing required else NULL */
|
||||
static
|
||||
@@ -584,7 +607,7 @@ rbt_balance_right(
|
||||
return(node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Rebalance the left sub-tree after deletion.
|
||||
@return node to rebalance if more rebalancing required else NULL */
|
||||
static
|
||||
@@ -644,7 +667,7 @@ rbt_balance_left(
|
||||
return(node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Delete the node and rebalance the tree if necessary */
|
||||
static
|
||||
void
|
||||
@@ -696,7 +719,7 @@ rbt_remove_node_and_rebalance(
|
||||
--tree->n_nodes;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Recursively free the nodes. */
|
||||
static
|
||||
void
|
||||
@@ -713,7 +736,7 @@ rbt_free_node(
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Free all the nodes and free the tree. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
@@ -726,7 +749,7 @@ rbt_free(
|
||||
ut_free(tree);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Create an instance of a red black tree.
|
||||
@return an empty rb tree */
|
||||
UNIV_INTERN
|
||||
@@ -764,7 +787,7 @@ rbt_create(
|
||||
return(tree);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Generic insert of a value in the rb tree.
|
||||
@return inserted node */
|
||||
UNIV_INTERN
|
||||
@@ -793,7 +816,7 @@ rbt_insert(
|
||||
return(node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Add a new node to the tree, useful for data that is pre-sorted.
|
||||
@return appended node */
|
||||
UNIV_INTERN
|
||||
@@ -831,7 +854,7 @@ rbt_add_node(
|
||||
return(node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find a matching node in the rb tree.
|
||||
@return NULL if not found else the node where key was found */
|
||||
UNIV_INTERN
|
||||
@@ -859,7 +882,7 @@ rbt_lookup(
|
||||
return(current != tree->nil ? current : NULL);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Delete a node indentified by key.
|
||||
@return TRUE if success FALSE if not found */
|
||||
UNIV_INTERN
|
||||
@@ -882,7 +905,7 @@ rbt_delete(
|
||||
return(deleted);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Remove a node from the rb tree, the node is not free'd, that is the
|
||||
callers responsibility.
|
||||
@return deleted node but without the const */
|
||||
@@ -906,7 +929,7 @@ rbt_remove_node(
|
||||
return((ib_rbt_node_t*) const_node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the node that has the lowest key that is >= key.
|
||||
@return node satisfying the lower bound constraint or NULL */
|
||||
UNIV_INTERN
|
||||
@@ -940,7 +963,7 @@ rbt_lower_bound(
|
||||
return(lb_node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the node that has the greatest key that is <= key.
|
||||
@return node satisfying the upper bound constraint or NULL */
|
||||
UNIV_INTERN
|
||||
@@ -974,7 +997,7 @@ rbt_upper_bound(
|
||||
return(ub_node);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the node that has the greatest key that is <= key.
|
||||
@return value of result */
|
||||
UNIV_INTERN
|
||||
@@ -1008,7 +1031,7 @@ rbt_search(
|
||||
return(parent->result);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Find the node that has the greatest key that is <= key. But use the
|
||||
supplied comparison function.
|
||||
@return value of result */
|
||||
@@ -1044,7 +1067,7 @@ rbt_search_cmp(
|
||||
return(parent->result);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the left most node in the tree. */
|
||||
UNIV_INTERN
|
||||
const ib_rbt_node_t*
|
||||
@@ -1064,7 +1087,7 @@ rbt_first(
|
||||
return(first);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the right most node in the tree.
|
||||
@return the rightmost node or NULL */
|
||||
UNIV_INTERN
|
||||
@@ -1084,7 +1107,7 @@ rbt_last(
|
||||
return(last);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the next node.
|
||||
@return node next from current */
|
||||
UNIV_INTERN
|
||||
@@ -1097,7 +1120,7 @@ rbt_next(
|
||||
return(current ? rbt_find_successor(tree, current) : NULL);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Return the previous node.
|
||||
@return node prev from current */
|
||||
UNIV_INTERN
|
||||
@@ -1110,7 +1133,7 @@ rbt_prev(
|
||||
return(current ? rbt_find_predecessor(tree, current) : NULL);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Reset the tree. Delete all the nodes. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
@@ -1124,7 +1147,7 @@ rbt_clear(
|
||||
tree->root->left = tree->root->right = tree->nil;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Merge the node from dst into src. Return the number of nodes merged.
|
||||
@return no. of recs merged */
|
||||
UNIV_INTERN
|
||||
@@ -1153,7 +1176,7 @@ rbt_merge_uniq(
|
||||
return(n_merged);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Merge the node from dst into src. Return the number of nodes merged.
|
||||
Delete the nodes from src after copying node to dst. As a side effect
|
||||
the duplicates will be left untouched in the src.
|
||||
@@ -1201,7 +1224,7 @@ rbt_merge_uniq_destructive(
|
||||
return(rbt_size(dst) - old_size);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Check that every path from the root to the leaves has the same count and
|
||||
the tree nodes are in order.
|
||||
@return TRUE if OK FALSE otherwise */
|
||||
@@ -1218,7 +1241,7 @@ rbt_validate(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
/**********************************************************************//**
|
||||
Iterate over the tree in depth first order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
|
Reference in New Issue
Block a user