1
0
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:
Vasil Dimov
2010-04-19 20:53:16 +03:00
39 changed files with 2835 additions and 1416 deletions

View File

@@ -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;

View File

@@ -3882,6 +3882,7 @@ btr_blob_free(
if there is one */
mtr_t* mtr) /*!< in: mini-transaction to commit */
{
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);
@@ -3889,7 +3890,7 @@ btr_blob_free(
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);
}

View File

@@ -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);

View File

@@ -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_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[] */
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_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[] */
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(
/*================*/
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(
/*=================*/
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,8 +244,10 @@ static
void*
buf_buddy_alloc_from(
/*=================*/
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 i, /*!< in: index of
buf_pool->zip_free[] */
ulint j) /*!< in: size of buf as an index
of buf_pool->zip_free[] */
{
@@ -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(
/*================*/
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 */
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(
/*===============*/
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[] */
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,6 +518,7 @@ UNIV_INTERN
void
buf_buddy_free_low(
/*===============*/
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[],
@@ -521,24 +527,24 @@ buf_buddy_free_low(
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

View File

@@ -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,15 +520,19 @@ buf_read_ibuf_merge_pages(
#ifdef UNIV_IBUF_DEBUG
ut_a(n_stored < UNIV_PAGE_SIZE);
#endif
for (i = 0; i < n_stored; i++) {
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);
}
for (i = 0; i < n_stored; i++) {
ulint zip_size = fil_space_get_zip_size(space_ids[i]);
ulint err;
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
goto tablespace_deleted;
@@ -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) {

View File

@@ -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++) {

View File

@@ -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),

View File

@@ -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 */
{
TABLE* table = (TABLE *) tables->table;
int status = 0;
TABLE* table = (TABLE *) tables->table;
DBUG_ENTER("i_s_cmpmem_fill_low");
@@ -1369,22 +1377,33 @@ 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;
status = 0;
buf_pool = buf_pool_from_array(i);
buf_pool_mutex_enter(buf_pool);
for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
buf_buddy_stat_t* buddy_stat = &buf_buddy_stat[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(buddy_stat->used);
table->field[2]->store(UNIV_LIKELY(x < BUF_BUDDY_SIZES)
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[3]->store((longlong) buddy_stat->relocated, true);
table->field[4]->store(
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. */
/* This is protected by buf_pool->mutex. */
buddy_stat->relocated = 0;
buddy_stat->relocated_usec = 0;
}
@@ -1395,7 +1414,13 @@ i_s_cmpmem_fill_low(
}
}
buf_pool_mutex_exit();
buf_pool_mutex_exit(buf_pool);
if (status) {
break;
}
}
DBUG_RETURN(status);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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,6 +58,7 @@ UNIV_INTERN
void
buf_buddy_free_low(
/*===============*/
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[],
@@ -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(
/*===========*/
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 */
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

View File

@@ -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,21 +184,29 @@ 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(
/*============*/
buf_pool_t* buf_pool, /*!< buffer pool instance */
ulint zip_size); /*!< in: compressed page size in bytes,
or 0 if uncompressed tablespace */
/********************************************************************//**
@@ -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,6 +570,7 @@ UNIV_INTERN
buf_block_t*
buf_pool_contains_zip(
/*==================*/
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(
/*==================*/
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) */
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(
/*==============*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset);/*!< in: offset of the page within space */
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(
/*===============*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset);/*!< in: offset of the page within space */
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,8 +1115,9 @@ 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(
/*==============*/
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));
/****************************************************************//**
@@ -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 */
/* @} */

View File

@@ -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(
/*==================*/
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) */
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(
/*==============*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */
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(
/*===============*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint space, /*!< in: space id */
ulint offset) /*!< in: offset of the page within space */
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 */

View File

@@ -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

View File

@@ -33,6 +33,7 @@ UNIV_INTERN
void
buf_flush_insert_into_flush_list(
/*=============================*/
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 */
/********************************************************************//**
@@ -43,6 +44,7 @@ UNIV_INTERN
void
buf_flush_insert_sorted_into_flush_list(
/*====================================*/
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 */
@@ -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);
}

View File

@@ -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
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. */
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,6 +153,7 @@ UNIV_INTERN
buf_block_t*
buf_LRU_get_free_block(
/*===================*/
buf_pool_t* buf_pool, /*!< in: preferred buffer pool */
ulint zip_size); /*!< in: compressed page size in bytes,
or 0 if uncompressed tablespace */
@@ -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;
/********************************************************************//**

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
n_pages = buf_flush_list(ULINT_MAX, IB_ULONGLONG_MAX);
ut_a(n_pages != ULINT_UNDEFINED);
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
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);

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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;
@@ -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++;
@@ -2610,10 +2621,11 @@ loop:
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();

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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