Commit 2018ce35 authored by marko's avatar marko

branches/zip: Implement resizeable buffer pool.

mysql.patch: Patch to change or add variables to MySQL

innodb.patch: Patch to make the master thread poll requests to resize
the buffer pool.

Replace srv_pool_size and innobase_buffer_pool_size
with srv_buf_pool_size, srv_buf_pool_old_size,
and srv_buf_pool_curr_size.

Add buf_chunk_t, a collection of buf_block_t.
parent 8e8719da
...@@ -215,6 +215,15 @@ ibool buf_debug_prints = FALSE; /* If this is set TRUE, ...@@ -215,6 +215,15 @@ ibool buf_debug_prints = FALSE; /* If this is set TRUE,
read-ahead or flush occurs */ read-ahead or flush occurs */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/* A chunk of buffers. The buffer pool is allocated in chunks. */
struct buf_chunk_struct{
ulint mem_size; /* allocated size of the chunk */
ulint size; /* size of frames[] and blocks[] */
void* mem; /* pointer to the memory area which
was allocated for the frames */
buf_block_t* blocks; /* array of buffer control blocks */
};
/************************************************************************ /************************************************************************
Calculates a page checksum which is stored to the page when it is written Calculates a page checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value on to a file. Note that we must be careful to calculate the same value on
...@@ -627,70 +636,220 @@ buf_block_init( ...@@ -627,70 +636,220 @@ buf_block_init(
} }
/************************************************************************ /************************************************************************
Creates the buffer pool. */ Allocates a chunk of buffer frames. */
static
buf_pool_t* buf_chunk_t*
buf_pool_init( buf_chunk_init(
/*==========*/ /*===========*/
/* out, own: buf_pool object, NULL if not /* out: chunk, or NULL on failure */
enough memory or error */ buf_chunk_t* chunk, /* out: chunk of buffers */
ulint curr_size) /* in: current size to use */ ulint mem_size) /* in: requested size in bytes */
{ {
buf_block_t* block;
byte* frame; byte* frame;
ulint i; ulint i;
buf_block_t* block;
buf_pool = mem_alloc(sizeof(buf_pool_t)); /* Round down to a multiple of page size,
although it already should be. */
mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
/* Reserve space for the block descriptors. */
mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
/* 1. Initialize general fields chunk->mem_size = mem_size;
------------------------------- */ chunk->mem = os_mem_alloc_large(&chunk->mem_size);
mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
mutex_enter(&(buf_pool->mutex));
buf_pool->frame_mem_size = (curr_size + 1) * UNIV_PAGE_SIZE;
buf_pool->frame_mem = os_mem_alloc_large(&buf_pool->frame_mem_size);
if (UNIV_UNLIKELY(buf_pool->frame_mem == NULL)) { if (UNIV_UNLIKELY(chunk->mem == NULL)) {
return(NULL); return(NULL);
} }
/* Align pointer to the first frame */ /* Allocate the block descriptors from
the start of the memory block. */
frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE); chunk->blocks = chunk->mem;
curr_size = buf_pool->frame_mem_size / UNIV_PAGE_SIZE /* Align pointer to the first frame */
- (frame != buf_pool->frame_mem);
buf_pool->blocks = ut_malloc(sizeof(buf_block_t) * curr_size); frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
- (frame != chunk->mem);
if (UNIV_UNLIKELY(buf_pool->blocks == NULL)) { /* Subtract the space needed for block descriptors. */
{
ulint size = chunk->size;
os_mem_free_large(buf_pool->frame_mem, while (frame < (byte*) (chunk->blocks + size)) {
buf_pool->frame_mem_size); frame += UNIV_PAGE_SIZE;
buf_pool->frame_mem = NULL; size--;
}
return(NULL); chunk->size = size;
} }
buf_pool->curr_size = curr_size;
/* Init block structs and assign frames for them. Then we /* Init block structs and assign frames for them. Then we
assign the frames to the first blocks (we already mapped the assign the frames to the first blocks (we already mapped the
memory above). */ memory above). */
for (i = 0; i < curr_size; i++) { block = chunk->blocks;
block = buf_pool_get_nth_block(buf_pool, i); for (i = chunk->size; i--; ) {
buf_block_init(block, frame); buf_block_init(block, frame);
#ifdef HAVE_purify
/* Wipe contents of frame to eliminate a Purify warning */
memset(block->frame, '\0', UNIV_PAGE_SIZE);
#endif
/* Add the block to the free list */
UT_LIST_ADD_LAST(free, buf_pool->free, block);
block->in_free_list = TRUE;
block++;
frame += UNIV_PAGE_SIZE; frame += UNIV_PAGE_SIZE;
} }
buf_pool->page_hash = hash_create(2 * curr_size); return(chunk);
}
/*************************************************************************
Checks that all file pages in the buffer chunk are in a replaceable state. */
static
const buf_block_t*
buf_chunk_not_freed(
/*================*/
/* out: address of a non-free block,
or NULL if all freed */
buf_chunk_t* chunk) /* in: chunk being checked */
{
buf_block_t* block;
ulint i;
ut_ad(buf_pool);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */
block = chunk->blocks;
for (i = chunk->size; i--; block++) {
mutex_enter(&block->mutex);
if (block->state == BUF_BLOCK_FILE_PAGE
&& !buf_flush_ready_for_replace(block)) {
mutex_exit(&block->mutex);
return(block);
}
mutex_exit(&block->mutex);
}
return(NULL);
}
/*************************************************************************
Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state. */
static
ibool
buf_chunk_all_free(
/*===============*/
/* out: TRUE if all freed */
const buf_chunk_t* chunk) /* in: chunk being checked */
{
const buf_block_t* block;
ulint i;
ut_ad(buf_pool);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */
block = chunk->blocks;
for (i = chunk->size; i--; block++) {
if (block->state != BUF_BLOCK_NOT_USED) {
return(FALSE);
}
}
return(TRUE);
}
/************************************************************************
Frees a chunk of buffer frames. */
static
void
buf_chunk_free(
/*===========*/
buf_chunk_t* chunk) /* out: chunk of buffers */
{
buf_block_t* block;
const buf_block_t* block_end;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */
block_end = chunk->blocks + chunk->size;
for (block = chunk->blocks; block < block_end; block++) {
ut_a(block->state == BUF_BLOCK_NOT_USED);
ut_a(!block->page_zip.data);
/* Remove the block from the free list. */
ut_a(block->in_free_list);
UT_LIST_REMOVE(free, buf_pool->free, block);
/* Free the latches. */
mutex_free(&block->mutex);
rw_lock_free(&block->lock);
#ifdef UNIV_SYNC_DEBUG
rw_lock_free(&block->debug_latch);
#endif /* UNIV_SYNC_DEBUG */
}
os_mem_free_large(chunk->mem, chunk->mem_size);
}
/************************************************************************
Creates the buffer pool. */
buf_pool_t*
buf_pool_init(void)
/*===============*/
/* out, own: buf_pool object, NULL if not
enough memory or error */
{
buf_chunk_t* chunk;
ulint i;
buf_pool = mem_alloc(sizeof(buf_pool_t));
/* 1. Initialize general fields
------------------------------- */
mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
mutex_enter(&(buf_pool->mutex));
buf_pool->n_chunks = 1;
buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
UT_LIST_INIT(buf_pool->free);
if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
mem_free(chunk);
mem_free(buf_pool);
buf_pool = NULL;
return(NULL);
}
srv_buf_pool_old_size = srv_buf_pool_size;
buf_pool->curr_size = chunk->size;
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
buf_pool->n_pend_reads = 0; buf_pool->n_pend_reads = 0;
...@@ -727,31 +886,128 @@ buf_pool_init( ...@@ -727,31 +886,128 @@ buf_pool_init(
buf_pool->LRU_old = NULL; buf_pool->LRU_old = NULL;
/* Add control blocks to the free list */ mutex_exit(&(buf_pool->mutex));
UT_LIST_INIT(buf_pool->free);
for (i = 0; i < curr_size; i++) { btr_search_sys_create(buf_pool->curr_size
* UNIV_PAGE_SIZE / sizeof(void*) / 64);
block = buf_pool_get_nth_block(buf_pool, i); return(buf_pool);
}
if (block->frame) { /************************************************************************
/* Wipe contents of frame to eliminate a Purify Resizes the buffer pool. */
warning */
#ifdef HAVE_purify void
memset(block->frame, '\0', UNIV_PAGE_SIZE); buf_pool_resize(void)
#endif /*=================*/
{
buf_chunk_t* chunks;
buf_chunk_t* chunk;
mutex_enter(&buf_pool->mutex);
if (srv_buf_pool_old_size == srv_buf_pool_size) {
goto func_exit;
}
if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
/* Shrink the buffer pool by at least one megabyte */
ulint chunk_size
= (srv_buf_pool_curr_size - srv_buf_pool_size)
/ UNIV_PAGE_SIZE;
ulint max_size;
buf_chunk_t* max_chunk;
shrink_again:
if (buf_pool->n_chunks <= 1) {
/* Cannot shrink if there is only one chunk */
goto func_done;
} }
UT_LIST_ADD_LAST(free, buf_pool->free, block); /* Search for the largest free chunk
block->in_free_list = TRUE; not larger than the size difference */
chunks = buf_pool->chunks;
chunk = chunks + buf_pool->n_chunks;
max_size = 0;
max_chunk = NULL;
while (--chunk >= chunks) {
if (chunk->size <= chunk_size
&& chunk->size > max_size
&& buf_chunk_all_free(chunk)) {
max_size = chunk->size;
max_chunk = chunk;
}
}
if (!max_size) {
/* Cannot shrink: try again later
(do not assign srv_buf_pool_old_size) */
goto func_exit;
}
srv_buf_pool_old_size = srv_buf_pool_size;
/* Rewrite buf_pool->chunks. Copy everything but max_chunk. */
chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
memcpy(chunks, buf_pool->chunks,
(max_chunk - buf_pool->chunks) * sizeof *chunks);
memcpy(chunks + (max_chunk - buf_pool->chunks),
max_chunk + 1,
buf_pool->chunks + buf_pool->n_chunks
- (max_chunk + 1));
ut_a(buf_pool->curr_size > max_chunk->size);
buf_pool->curr_size -= max_chunk->size;
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
chunk_size -= max_chunk->size;
buf_chunk_free(max_chunk);
mem_free(buf_pool->chunks);
buf_pool->chunks = chunks;
buf_pool->n_chunks--;
/* Allow a slack of one megabyte. */
if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
goto shrink_again;
}
} else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
/* Enlarge the buffer pool by at least one megabyte */
ulint mem_size
= srv_buf_pool_size - srv_buf_pool_curr_size;
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
* sizeof *chunks);
chunk = &chunks[buf_pool->n_chunks];
if (!buf_chunk_init(chunk, mem_size)) {
mem_free(chunks);
} else {
buf_pool->curr_size += chunk->size;
srv_buf_pool_curr_size = buf_pool->curr_size
* UNIV_PAGE_SIZE;
mem_free(buf_pool->chunks);
buf_pool->chunks = chunks;
buf_pool->n_chunks++;
}
} }
mutex_exit(&(buf_pool->mutex)); /* TODO: reinitialize buf_pool->page_hash */
btr_search_sys_create(curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64); func_done:
srv_buf_pool_old_size = srv_buf_pool_size;
return(buf_pool); func_exit:
mutex_exit(&buf_pool->mutex);
} }
/************************************************************************ /************************************************************************
...@@ -1979,7 +2235,7 @@ ibool ...@@ -1979,7 +2235,7 @@ ibool
buf_validate(void) buf_validate(void)
/*==============*/ /*==============*/
{ {
buf_block_t* block; buf_chunk_t* chunk;
ulint i; ulint i;
ulint n_single_flush = 0; ulint n_single_flush = 0;
ulint n_lru_flush = 0; ulint n_lru_flush = 0;
...@@ -1993,58 +2249,67 @@ buf_validate(void) ...@@ -1993,58 +2249,67 @@ buf_validate(void)
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
for (i = 0; i < buf_pool->curr_size; i++) { chunk = buf_pool->chunks;
block = buf_pool_get_nth_block(buf_pool, i); for (i = buf_pool->n_chunks; i--; chunk++) {
mutex_enter(&block->mutex); ulint j;
buf_block_t* block = chunk->blocks;
for (j = chunk->size; j--; block++) {
mutex_enter(&block->mutex);
if (block->state == BUF_BLOCK_FILE_PAGE) { if (block->state == BUF_BLOCK_FILE_PAGE) {
ut_a(buf_page_hash_get(block->space, ut_a(buf_page_hash_get(block->space,
block->offset) == block); block->offset)
n_page++; == block);
n_page++;
#ifdef UNIV_IBUF_DEBUG #ifdef UNIV_IBUF_DEBUG
ut_a((block->io_fix == BUF_IO_READ) ut_a((block->io_fix == BUF_IO_READ)
|| ibuf_count_get(block->space, block->offset) || !ibuf_count_get(block->space,
== 0); block->offset));
#endif #endif
if (block->io_fix == BUF_IO_WRITE) { if (block->io_fix == BUF_IO_WRITE) {
if (block->flush_type == BUF_FLUSH_LRU) { switch (block->flush_type) {
n_lru_flush++; case BUF_FLUSH_LRU:
ut_a(rw_lock_is_locked( n_lru_flush++;
&block->lock, ut_a(rw_lock_is_locked(
RW_LOCK_SHARED)); &block->lock,
} else if (block->flush_type RW_LOCK_SHARED));
== BUF_FLUSH_LIST) { break;
n_list_flush++; case BUF_FLUSH_LIST:
} else if (block->flush_type n_list_flush++;
== BUF_FLUSH_SINGLE_PAGE) { break;
n_single_flush++; case BUF_FLUSH_SINGLE_PAGE:
} else { n_single_flush++;
ut_error; break;
} default:
ut_error;
}
} else if (block->io_fix == BUF_IO_READ) { } else if (block->io_fix == BUF_IO_READ) {
ut_a(rw_lock_is_locked(&(block->lock), ut_a(rw_lock_is_locked(&block->lock,
RW_LOCK_EX)); RW_LOCK_EX));
} }
n_lru++; n_lru++;
if (ut_dulint_cmp(block->oldest_modification, if (ut_dulint_cmp(block->oldest_modification,
ut_dulint_zero) > 0) { ut_dulint_zero) > 0) {
n_flush++; n_flush++;
}
} else if (block->state == BUF_BLOCK_NOT_USED) {
n_free++;
} }
} else if (block->state == BUF_BLOCK_NOT_USED) { mutex_exit(&block->mutex);
n_free++;
} }
mutex_exit(&block->mutex);
} }
if (n_lru + n_free > buf_pool->curr_size) { if (n_lru + n_free > buf_pool->curr_size) {
...@@ -2090,7 +2355,7 @@ buf_print(void) ...@@ -2090,7 +2355,7 @@ buf_print(void)
ulint j; ulint j;
dulint id; dulint id;
ulint n_found; ulint n_found;
buf_frame_t* frame; buf_chunk_t* chunk;
dict_index_t* index; dict_index_t* index;
ut_ad(buf_pool); ut_ad(buf_pool);
...@@ -2125,30 +2390,38 @@ buf_print(void) ...@@ -2125,30 +2390,38 @@ buf_print(void)
n_found = 0; n_found = 0;
for (i = 0; i < size; i++) { chunk = buf_pool->chunks;
frame = buf_pool_get_nth_block(buf_pool, i)->frame;
if (fil_page_get_type(frame) == FIL_PAGE_INDEX) { for (i = buf_pool->n_chunks; i--; chunk++) {
buf_block_t* block = chunk->blocks;
ulint n_blocks = chunk->size;
id = btr_page_get_index_id(frame); for (; n_blocks--; block++) {
const buf_frame_t* frame = block->frame;
/* Look for the id in the index_ids array */ if (fil_page_get_type(frame) == FIL_PAGE_INDEX) {
j = 0;
while (j < n_found) { id = btr_page_get_index_id(frame);
if (ut_dulint_cmp(index_ids[j], id) == 0) { /* Look for the id in the index_ids array */
counts[j]++; j = 0;
break; while (j < n_found) {
if (ut_dulint_cmp(index_ids[j],
id) == 0) {
counts[j]++;
break;
}
j++;
} }
j++;
}
if (j == n_found) { if (j == n_found) {
n_found++; n_found++;
index_ids[j] = id; index_ids[j] = id;
counts[j] = 1; counts[j] = 1;
}
} }
} }
} }
...@@ -2184,17 +2457,26 @@ Returns the number of latched pages in the buffer pool. */ ...@@ -2184,17 +2457,26 @@ Returns the number of latched pages in the buffer pool. */
ulint ulint
buf_get_latched_pages_number(void) buf_get_latched_pages_number(void)
{ {
buf_block_t* block; buf_chunk_t* chunk;
ulint i; ulint i;
ulint fixed_pages_number = 0; ulint fixed_pages_number = 0;
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
for (i = 0; i < buf_pool->curr_size; i++) { chunk = buf_pool->chunks;
for (i = buf_pool->n_chunks; i--; chunk++) {
buf_block_t* block;
ulint j;
block = chunk->blocks;
block = buf_pool_get_nth_block(buf_pool, i); for (j = chunk->size; j--; block++) {
if (block->magic_n != BUF_BLOCK_MAGIC_N) {
continue;
}
if (block->magic_n == BUF_BLOCK_MAGIC_N) {
mutex_enter(&block->mutex); mutex_enter(&block->mutex);
if (block->buf_fix_count != 0 || block->io_fix != 0) { if (block->buf_fix_count != 0 || block->io_fix != 0) {
...@@ -2340,32 +2622,26 @@ ibool ...@@ -2340,32 +2622,26 @@ ibool
buf_all_freed(void) buf_all_freed(void)
/*===============*/ /*===============*/
{ {
buf_block_t* block; buf_chunk_t* chunk;
ulint i; ulint i;
ut_ad(buf_pool); ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
for (i = 0; i < buf_pool->curr_size; i++) { chunk = buf_pool->chunks;
block = buf_pool_get_nth_block(buf_pool, i);
mutex_enter(&block->mutex);
if (block->state == BUF_BLOCK_FILE_PAGE) { for (i = buf_pool->n_chunks; i--; chunk++) {
if (!buf_flush_ready_for_replace(block)) { const buf_block_t* block = buf_chunk_not_freed(chunk);
fprintf(stderr, if (UNIV_LIKELY_NULL(block)) {
"Page %lu %lu still fixed or dirty\n", fprintf(stderr,
(ulong) block->space, "Page %lu %lu still fixed or dirty\n",
(ulong) block->offset); (ulong) block->space,
ut_error; (ulong) block->offset);
} ut_error;
} }
mutex_exit(&block->mutex);
} }
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
......
...@@ -157,7 +157,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group, ...@@ -157,7 +157,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_lock_wait_timeout, innobase_force_recovery, innobase_lock_wait_timeout, innobase_force_recovery,
innobase_open_files; innobase_open_files;
longlong innobase_buffer_pool_size, innobase_log_file_size; longlong innobase_log_file_size;
/* The default values for the following char* start-up parameters /* The default values for the following char* start-up parameters
are determined in innobase_init below: */ are determined in innobase_init below: */
...@@ -1404,7 +1404,7 @@ innobase_init(void *p) ...@@ -1404,7 +1404,7 @@ innobase_init(void *p)
/* Check that values don't overflow on 32-bit systems. */ /* Check that values don't overflow on 32-bit systems. */
if (sizeof(ulint) == 4) { if (sizeof(ulint) == 4) {
if (innobase_buffer_pool_size > UINT_MAX32) { if (srv_buf_pool_size > UINT_MAX32) {
sql_print_error( sql_print_error(
"innobase_buffer_pool_size can't be over 4GB" "innobase_buffer_pool_size can't be over 4GB"
" on 32-bit systems"); " on 32-bit systems");
...@@ -1533,14 +1533,6 @@ innobase_init(void *p) ...@@ -1533,14 +1533,6 @@ innobase_init(void *p)
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
srv_log_buffer_size = (ulint) innobase_log_buffer_size; srv_log_buffer_size = (ulint) innobase_log_buffer_size;
/* We set srv_pool_size here in units of 1 kB. InnoDB internally
changes the value so that it becomes the number of database pages. */
/* Careful here: we first convert the signed long int to ulint
and only after that divide */
srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size; srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
srv_n_file_io_threads = (ulint) innobase_file_io_threads; srv_n_file_io_threads = (ulint) innobase_file_io_threads;
......
...@@ -207,7 +207,7 @@ extern SHOW_VAR innodb_status_variables[]; ...@@ -207,7 +207,7 @@ extern SHOW_VAR innodb_status_variables[];
extern ulong innobase_fast_shutdown; extern ulong innobase_fast_shutdown;
extern ulong innobase_large_page_size; extern ulong innobase_large_page_size;
extern long innobase_mirrored_log_groups, innobase_log_files_in_group; extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
extern longlong innobase_buffer_pool_size, innobase_log_file_size; extern longlong innobase_log_file_size;
extern long innobase_log_buffer_size; extern long innobase_log_buffer_size;
extern long innobase_additional_mem_pool_size; extern long innobase_additional_mem_pool_size;
extern long innobase_file_io_threads, innobase_lock_wait_timeout; extern long innobase_file_io_threads, innobase_lock_wait_timeout;
...@@ -225,6 +225,8 @@ extern my_bool innobase_log_archive, ...@@ -225,6 +225,8 @@ extern my_bool innobase_log_archive,
innobase_file_per_table, innobase_locks_unsafe_for_binlog, innobase_file_per_table, innobase_locks_unsafe_for_binlog,
innobase_create_status_file; innobase_create_status_file;
extern "C" { extern "C" {
extern ulong srv_buf_pool_curr_size;
extern ulong srv_buf_pool_size;
extern ulong srv_max_buf_pool_modified_pct; extern ulong srv_max_buf_pool_modified_pct;
extern ulong srv_max_purge_lag; extern ulong srv_max_purge_lag;
extern ulong srv_auto_extend_increment; extern ulong srv_auto_extend_increment;
......
...@@ -69,11 +69,16 @@ extern ulint srv_buf_pool_write_requests; /* variable to count write request ...@@ -69,11 +69,16 @@ extern ulint srv_buf_pool_write_requests; /* variable to count write request
Creates the buffer pool. */ Creates the buffer pool. */
buf_pool_t* buf_pool_t*
buf_pool_init( buf_pool_init(void);
/*==========*/ /*===============*/
/* out, own: buf_pool object, NULL if not /* out, own: buf_pool object, NULL if not
enough memory or error */ enough memory or error */
ulint curr_size); /* in: current size to use */ /************************************************************************
Resizes the buffer pool. */
void
buf_pool_resize(void);
/*=================*/
/************************************************************************* /*************************************************************************
Gets the current size of buffer buf_pool in bytes. */ Gets the current size of buffer buf_pool in bytes. */
UNIV_INLINE UNIV_INLINE
...@@ -833,11 +838,8 @@ struct buf_pool_struct{ ...@@ -833,11 +838,8 @@ struct buf_pool_struct{
mutex_t mutex; /* mutex protecting the buffer pool mutex_t mutex; /* mutex protecting the buffer pool
struct and control blocks, except the struct and control blocks, except the
read-write lock in them */ read-write lock in them */
byte* frame_mem; /* pointer to the memory area which ulint n_chunks; /* number of buffer pool chunks */
was allocated for the frames */ buf_chunk_t* chunks; /* buffer pool chunks */
ulint frame_mem_size; /* allocated length of frame_mem
in bytes */
buf_block_t* blocks; /* array of buffer control blocks */
ulint curr_size; /* current pool size in pages */ ulint curr_size; /* current pool size in pages */
hash_table_t* page_hash; /* hash table of the file pages */ hash_table_t* page_hash; /* hash table of the file pages */
......
...@@ -42,22 +42,6 @@ buf_pool_get_curr_size(void) ...@@ -42,22 +42,6 @@ buf_pool_get_curr_size(void)
return(buf_pool->curr_size * UNIV_PAGE_SIZE); return(buf_pool->curr_size * UNIV_PAGE_SIZE);
} }
/***********************************************************************
Accessor function for block array. */
UNIV_INLINE
buf_block_t*
buf_pool_get_nth_block(
/*===================*/
/* out: pointer to block */
buf_pool_t* buf_pool,/* in: buf_pool */
ulint i) /* in: index of the block */
{
ut_ad(buf_pool);
ut_ad(i < buf_pool->curr_size);
return(i + buf_pool->blocks);
}
/************************************************************************ /************************************************************************
Gets the smallest oldest_modification lsn for any page in the pool. Returns Gets the smallest oldest_modification lsn for any page in the pool. Returns
ut_dulint_zero if all modified pages have been flushed to disk. */ ut_dulint_zero if all modified pages have been flushed to disk. */
...@@ -114,8 +98,6 @@ buf_block_get_frame( ...@@ -114,8 +98,6 @@ buf_block_get_frame(
buf_block_t* block) /* in: pointer to the control block */ buf_block_t* block) /* in: pointer to the control block */
{ {
ut_ad(block); ut_ad(block);
ut_ad(block >= buf_pool->blocks);
ut_ad(block < buf_pool->blocks + buf_pool->curr_size);
ut_ad(block->state != BUF_BLOCK_NOT_USED); ut_ad(block->state != BUF_BLOCK_NOT_USED);
ut_ad((block->state != BUF_BLOCK_FILE_PAGE) ut_ad((block->state != BUF_BLOCK_FILE_PAGE)
|| (block->buf_fix_count > 0)); || (block->buf_fix_count > 0));
...@@ -133,8 +115,6 @@ buf_block_get_space( ...@@ -133,8 +115,6 @@ buf_block_get_space(
const buf_block_t* block) /* in: pointer to the control block */ const buf_block_t* block) /* in: pointer to the control block */
{ {
ut_ad(block); ut_ad(block);
ut_ad(block >= buf_pool->blocks);
ut_ad(block < buf_pool->blocks + buf_pool->curr_size);
ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0); ut_ad(block->buf_fix_count > 0);
...@@ -151,8 +131,6 @@ buf_block_get_page_no( ...@@ -151,8 +131,6 @@ buf_block_get_page_no(
const buf_block_t* block) /* in: pointer to the control block */ const buf_block_t* block) /* in: pointer to the control block */
{ {
ut_ad(block); ut_ad(block);
ut_ad(block >= buf_pool->blocks);
ut_ad(block < buf_pool->blocks + buf_pool->curr_size);
ut_a(block->state == BUF_BLOCK_FILE_PAGE); ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0); ut_ad(block->buf_fix_count > 0);
......
...@@ -94,8 +94,9 @@ ibool ...@@ -94,8 +94,9 @@ ibool
buf_flush_ready_for_replace( buf_flush_ready_for_replace(
/*========================*/ /*========================*/
/* out: TRUE if can replace immediately */ /* out: TRUE if can replace immediately */
buf_block_t* block); /* in: buffer control block, must be in state buf_block_t* block); /* in: buffer control block, must
BUF_BLOCK_FILE_PAGE and in the LRU list */ be in state BUF_BLOCK_FILE_PAGE
and in the LRU list */
/********************************************************************** /**********************************************************************
Validates the flush list. */ Validates the flush list. */
......
...@@ -10,6 +10,7 @@ Created 11/17/1995 Heikki Tuuri ...@@ -10,6 +10,7 @@ Created 11/17/1995 Heikki Tuuri
#define buf0types_h #define buf0types_h
typedef struct buf_block_struct buf_block_t; typedef struct buf_block_struct buf_block_t;
typedef struct buf_chunk_struct buf_chunk_t;
typedef struct buf_pool_struct buf_pool_t; typedef struct buf_pool_struct buf_pool_t;
/* The 'type' used of a buffer frame */ /* The 'type' used of a buffer frame */
......
...@@ -84,7 +84,9 @@ extern ulong srv_flush_log_at_trx_commit; ...@@ -84,7 +84,9 @@ extern ulong srv_flush_log_at_trx_commit;
extern byte srv_latin1_ordering[256];/* The sort order table of the latin1 extern byte srv_latin1_ordering[256];/* The sort order table of the latin1
character set */ character set */
extern ulint srv_pool_size; extern ulong srv_buf_pool_size; /* requested size in kilobytes */
extern ulong srv_buf_pool_old_size; /* previously requested size */
extern ulong srv_buf_pool_curr_size; /* current size in kilobytes */
extern ulint srv_mem_pool_size; extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size; extern ulint srv_lock_table_size;
...@@ -153,7 +155,6 @@ extern ulong srv_thread_sleep_delay; ...@@ -153,7 +155,6 @@ extern ulong srv_thread_sleep_delay;
extern ulint srv_spin_wait_delay; extern ulint srv_spin_wait_delay;
extern ibool srv_priority_boost; extern ibool srv_priority_boost;
extern ulint srv_pool_size;
extern ulint srv_mem_pool_size; extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size; extern ulint srv_lock_table_size;
......
Index: srv/srv0srv.c
===================================================================
--- srv/srv0srv.c (revision 1010)
+++ srv/srv0srv.c (working copy)
@@ -2183,6 +2182,12 @@ loop:
/* ---- When there is database activity by users, we cycle in this
loop */
+ if (UNIV_UNLIKELY(srv_buf_pool_size != srv_buf_pool_old_size)) {
+ srv_main_thread_op_info = "resizing buffer pool";
+
+ buf_pool_resize();
+ }
+
srv_main_thread_op_info = "reserving kernel mutex";
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
@@ -2543,6 +2548,12 @@ flush_loop:
master thread to wait for more server activity */
suspend_thread:
+ if (UNIV_UNLIKELY(srv_buf_pool_size != srv_buf_pool_old_size)) {
+ srv_main_thread_op_info = "resizing buffer pool";
+
+ buf_pool_resize();
+ }
+
srv_main_thread_op_info = "suspending";
mutex_enter(&kernel_mutex);
@@ -2553,7 +2564,9 @@ suspend_thread:
goto loop;
}
+#if 0
event = srv_suspend_thread();
+#endif
mutex_exit(&kernel_mutex);
@@ -2563,7 +2576,11 @@ suspend_thread:
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";
+#if 0
os_event_wait(event);
+#else
+ os_thread_sleep(1000000);
+#endif
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
/* This is only extra safety, the thread should exit
diff -pu mysql-5.1-bk/sql/mysqld.cc mysql-5.1-zip/sql/mysqld.cc
--- mysql-5.1-bk/sql/mysqld.cc 2006-11-09 16:01:19.000000000 +0200
+++ mysql-5.1-zip/sql/mysqld.cc 2006-11-13 12:54:04.000000000 +0200
@@ -370,7 +370,6 @@ extern long innobase_lock_scan_time;
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
extern longlong innobase_log_file_size;
extern long innobase_log_buffer_size;
-extern longlong innobase_buffer_pool_size;
extern long innobase_additional_mem_pool_size;
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
extern long innobase_force_recovery;
@@ -390,6 +389,8 @@ extern "C" {
extern ulong srv_max_buf_pool_modified_pct;
extern ulong srv_max_purge_lag;
extern ulong srv_auto_extend_increment;
+extern ulong srv_buf_pool_curr_size;
+extern ulong srv_buf_pool_size;
extern ulong srv_n_spin_wait_rounds;
extern ulong srv_n_free_tickets_to_enter;
extern ulong srv_thread_sleep_delay;
@@ -5801,9 +5802,9 @@ log and this option does nothing anymore
(gptr*) &srv_auto_extend_increment,
0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
{"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE,
- "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
- (gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0,
- GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
+ "The requested size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
+ (gptr*) &srv_buf_pool_size, (gptr*) &srv_buf_pool_size, 0,
+ GET_LL, REQUIRED_ARG, 8*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 0,
1024*1024L, 0},
{"innodb_commit_concurrency", OPT_INNODB_COMMIT_CONCURRENCY,
"Helps in performance tuning in heavily concurrent environments.",
diff -pu mysql-5.1-bk/sql/set_var.cc mysql-5.1-zip/sql/set_var.cc
--- mysql-5.1-bk/sql/set_var.cc 2006-11-09 16:01:19.000000000 +0200
+++ mysql-5.1-zip/sql/set_var.cc 2006-11-13 12:54:05.000000000 +0200
@@ -65,7 +65,6 @@ extern ulong innobase_fast_shutdown;
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
extern longlong innobase_log_file_size;
extern long innobase_log_buffer_size;
-extern longlong innobase_buffer_pool_size;
extern long innobase_additional_mem_pool_size;
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
extern long innobase_force_recovery;
@@ -81,6 +80,8 @@ extern my_bool innobase_log_archive,
innobase_locks_unsafe_for_binlog;
extern "C" {
+extern ulong srv_buf_pool_curr_size;
+extern ulong srv_buf_pool_size;
extern ulong srv_max_buf_pool_modified_pct;
extern ulong srv_max_purge_lag;
extern ulong srv_auto_extend_increment;
@@ -499,6 +500,8 @@ sys_var_thd_bool sys_innodb_support_xa("
&SV::innodb_support_xa);
sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment",
&srv_auto_extend_increment);
+sys_var_long_ptr sys_innodb_buffer_pool_size("innodb_buffer_pool_size",
+ &srv_buf_pool_size);
sys_var_long_ptr sys_innodb_sync_spin_loops("innodb_sync_spin_loops",
&srv_n_spin_wait_rounds);
sys_var_long_ptr sys_innodb_concurrency_tickets("innodb_concurrency_tickets",
@@ -818,7 +821,8 @@ SHOW_VAR init_vars[]= {
#ifdef WITH_INNOBASE_STORAGE_ENGINE
{"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
{sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS},
- {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONGLONG },
+ {sys_innodb_buffer_pool_size.name, (char*) &sys_innodb_buffer_pool_size, SHOW_SYS },
+ {"innodb_buffer_pool_curr_size", (char*) &srv_buf_pool_curr_size, SHOW_LONGLONG },
{"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL},
{sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS},
{sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS},
...@@ -159,10 +159,11 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1 ...@@ -159,10 +159,11 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF , 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
}; };
ulint srv_pool_size = ULINT_MAX; /* size in pages; MySQL inits ulong srv_buf_pool_size = ULINT_MAX; /* requested size
this to size in kilobytes but in kilobytes */
we normalize this to pages in ulong srv_buf_pool_old_size; /* previously requested size */
srv_boot() */ ulong srv_buf_pool_curr_size = 0; /* current size
in kilobytes */
ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */ ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */
ulint srv_lock_table_size = ULINT_MAX; ulint srv_lock_table_size = ULINT_MAX;
...@@ -1233,9 +1234,7 @@ srv_normalize_init_values(void) ...@@ -1233,9 +1234,7 @@ srv_normalize_init_values(void)
srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE; srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024); srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
srv_lock_table_size = 5 * srv_pool_size;
return(DB_SUCCESS); return(DB_SUCCESS);
} }
......
...@@ -1132,7 +1132,7 @@ innobase_start_or_create_for_mysql(void) ...@@ -1132,7 +1132,7 @@ innobase_start_or_create_for_mysql(void)
} }
/* Note that the call srv_boot() also changes the values of /* Note that the call srv_boot() also changes the values of
srv_pool_size etc. to the units used by InnoDB internally */ some variables to the units used by InnoDB internally */
/* Set the maximum number of threads which can wait for a semaphore /* Set the maximum number of threads which can wait for a semaphore
inside InnoDB: this is the 'sync wait array' size, as well as the inside InnoDB: this is the 'sync wait array' size, as well as the
...@@ -1147,15 +1147,12 @@ innobase_start_or_create_for_mysql(void) ...@@ -1147,15 +1147,12 @@ innobase_start_or_create_for_mysql(void)
NetWare. */ NetWare. */
srv_max_n_threads = 1000; srv_max_n_threads = 1000;
#else #else
if (srv_pool_size >= 1000 * 1024) { if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
/* Here we still have srv_pool_size counted /* If buffer pool is less than 1000 MB,
in kilobytes (in 4.0 this was in bytes)
srv_boot() converts the value to
pages; if buffer pool is less than 1000 MB,
assume fewer threads. */ assume fewer threads. */
srv_max_n_threads = 50000; srv_max_n_threads = 50000;
} else if (srv_pool_size >= 8 * 1024) { } else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
srv_max_n_threads = 10000; srv_max_n_threads = 10000;
} else { } else {
...@@ -1164,7 +1161,7 @@ innobase_start_or_create_for_mysql(void) ...@@ -1164,7 +1161,7 @@ innobase_start_or_create_for_mysql(void)
computers */ computers */
} }
#endif #endif
err = srv_boot(); /* This changes srv_pool_size to units of a page */ err = srv_boot();
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
...@@ -1230,7 +1227,7 @@ innobase_start_or_create_for_mysql(void) ...@@ -1230,7 +1227,7 @@ innobase_start_or_create_for_mysql(void)
fil_init(srv_max_n_open_files); fil_init(srv_max_n_open_files);
ret = buf_pool_init(srv_pool_size); ret = buf_pool_init();
if (ret == NULL) { if (ret == NULL) {
fprintf(stderr, fprintf(stderr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment