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,
read-ahead or flush occurs */
#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
to a file. Note that we must be careful to calculate the same value on
......@@ -627,70 +636,220 @@ buf_block_init(
}
/************************************************************************
Creates the buffer pool. */
buf_pool_t*
buf_pool_init(
/*==========*/
/* out, own: buf_pool object, NULL if not
enough memory or error */
ulint curr_size) /* in: current size to use */
Allocates a chunk of buffer frames. */
static
buf_chunk_t*
buf_chunk_init(
/*===========*/
/* out: chunk, or NULL on failure */
buf_chunk_t* chunk, /* out: chunk of buffers */
ulint mem_size) /* in: requested size in bytes */
{
buf_block_t* block;
byte* frame;
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
------------------------------- */
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);
chunk->mem_size = mem_size;
chunk->mem = os_mem_alloc_large(&chunk->mem_size);
if (UNIV_UNLIKELY(buf_pool->frame_mem == NULL)) {
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
return(NULL);
}
/* Align pointer to the first frame */
frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE);
/* Allocate the block descriptors from
the start of the memory block. */
chunk->blocks = chunk->mem;
curr_size = buf_pool->frame_mem_size / UNIV_PAGE_SIZE
- (frame != buf_pool->frame_mem);
/* Align pointer to the first frame */
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,
buf_pool->frame_mem_size);
buf_pool->frame_mem = NULL;
while (frame < (byte*) (chunk->blocks + size)) {
frame += UNIV_PAGE_SIZE;
size--;
}
return(NULL);
chunk->size = size;
}
buf_pool->curr_size = curr_size;
/* Init block structs and assign frames for them. Then we
assign the frames to the first blocks (we already mapped the
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);
#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;
}
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;
......@@ -727,31 +886,128 @@ buf_pool_init(
buf_pool->LRU_old = NULL;
/* Add control blocks to the free list */
UT_LIST_INIT(buf_pool->free);
mutex_exit(&(buf_pool->mutex));
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
warning */
/************************************************************************
Resizes the buffer pool. */
#ifdef HAVE_purify
memset(block->frame, '\0', UNIV_PAGE_SIZE);
#endif
void
buf_pool_resize(void)
/*=================*/
{
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);
block->in_free_list = TRUE;
/* Search for the largest free chunk
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
buf_validate(void)
/*==============*/
{
buf_block_t* block;
buf_chunk_t* chunk;
ulint i;
ulint n_single_flush = 0;
ulint n_lru_flush = 0;
......@@ -1993,58 +2249,67 @@ buf_validate(void)
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,
block->offset) == block);
n_page++;
ut_a(buf_page_hash_get(block->space,
block->offset)
== block);
n_page++;
#ifdef UNIV_IBUF_DEBUG
ut_a((block->io_fix == BUF_IO_READ)
|| ibuf_count_get(block->space, block->offset)
== 0);
ut_a((block->io_fix == BUF_IO_READ)
|| !ibuf_count_get(block->space,
block->offset));
#endif
if (block->io_fix == BUF_IO_WRITE) {
if (block->flush_type == BUF_FLUSH_LRU) {
n_lru_flush++;
ut_a(rw_lock_is_locked(
&block->lock,
RW_LOCK_SHARED));
} else if (block->flush_type
== BUF_FLUSH_LIST) {
n_list_flush++;
} else if (block->flush_type
== BUF_FLUSH_SINGLE_PAGE) {
n_single_flush++;
} else {
ut_error;
}
if (block->io_fix == BUF_IO_WRITE) {
switch (block->flush_type) {
case BUF_FLUSH_LRU:
n_lru_flush++;
ut_a(rw_lock_is_locked(
&block->lock,
RW_LOCK_SHARED));
break;
case BUF_FLUSH_LIST:
n_list_flush++;
break;
case BUF_FLUSH_SINGLE_PAGE:
n_single_flush++;
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),
RW_LOCK_EX));
}
ut_a(rw_lock_is_locked(&block->lock,
RW_LOCK_EX));
}
n_lru++;
n_lru++;
if (ut_dulint_cmp(block->oldest_modification,
ut_dulint_zero) > 0) {
n_flush++;
if (ut_dulint_cmp(block->oldest_modification,
ut_dulint_zero) > 0) {
n_flush++;
}
} else if (block->state == BUF_BLOCK_NOT_USED) {
n_free++;
}
} else if (block->state == BUF_BLOCK_NOT_USED) {
n_free++;
mutex_exit(&block->mutex);
}
mutex_exit(&block->mutex);
}
if (n_lru + n_free > buf_pool->curr_size) {
......@@ -2090,7 +2355,7 @@ buf_print(void)
ulint j;
dulint id;
ulint n_found;
buf_frame_t* frame;
buf_chunk_t* chunk;
dict_index_t* index;
ut_ad(buf_pool);
......@@ -2125,30 +2390,38 @@ buf_print(void)
n_found = 0;
for (i = 0; i < size; i++) {
frame = buf_pool_get_nth_block(buf_pool, i)->frame;
chunk = buf_pool->chunks;
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 */
j = 0;
if (fil_page_get_type(frame) == FIL_PAGE_INDEX) {
while (j < n_found) {
id = btr_page_get_index_id(frame);
if (ut_dulint_cmp(index_ids[j], id) == 0) {
counts[j]++;
/* Look for the id in the index_ids array */
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) {
n_found++;
index_ids[j] = id;
counts[j] = 1;
if (j == n_found) {
n_found++;
index_ids[j] = id;
counts[j] = 1;
}
}
}
}
......@@ -2184,17 +2457,26 @@ Returns the number of latched pages in the buffer pool. */
ulint
buf_get_latched_pages_number(void)
{
buf_block_t* block;
buf_chunk_t* chunk;
ulint i;
ulint fixed_pages_number = 0;
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);
if (block->buf_fix_count != 0 || block->io_fix != 0) {
......@@ -2340,32 +2622,26 @@ ibool
buf_all_freed(void)
/*===============*/
{
buf_block_t* block;
buf_chunk_t* chunk;
ulint i;
ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex));
for (i = 0; i < buf_pool->curr_size; i++) {
block = buf_pool_get_nth_block(buf_pool, i);
mutex_enter(&block->mutex);
chunk = buf_pool->chunks;
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,
"Page %lu %lu still fixed or dirty\n",
(ulong) block->space,
(ulong) block->offset);
ut_error;
}
if (UNIV_LIKELY_NULL(block)) {
fprintf(stderr,
"Page %lu %lu still fixed or dirty\n",
(ulong) block->space,
(ulong) block->offset);
ut_error;
}
mutex_exit(&block->mutex);
}
mutex_exit(&(buf_pool->mutex));
......
......@@ -157,7 +157,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_lock_wait_timeout, innobase_force_recovery,
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
are determined in innobase_init below: */
......@@ -1404,7 +1404,7 @@ innobase_init(void *p)
/* Check that values don't overflow on 32-bit systems. */
if (sizeof(ulint) == 4) {
if (innobase_buffer_pool_size > UINT_MAX32) {
if (srv_buf_pool_size > UINT_MAX32) {
sql_print_error(
"innobase_buffer_pool_size can't be over 4GB"
" on 32-bit systems");
......@@ -1533,14 +1533,6 @@ innobase_init(void *p)
#endif /* UNIV_LOG_ARCHIVE */
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_n_file_io_threads = (ulint) innobase_file_io_threads;
......
......@@ -207,7 +207,7 @@ extern SHOW_VAR innodb_status_variables[];
extern ulong innobase_fast_shutdown;
extern ulong innobase_large_page_size;
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_additional_mem_pool_size;
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
......@@ -225,6 +225,8 @@ extern my_bool innobase_log_archive,
innobase_file_per_table, innobase_locks_unsafe_for_binlog,
innobase_create_status_file;
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;
......
......@@ -69,11 +69,16 @@ extern ulint srv_buf_pool_write_requests; /* variable to count write request
Creates the buffer pool. */
buf_pool_t*
buf_pool_init(
/*==========*/
buf_pool_init(void);
/*===============*/
/* out, own: buf_pool object, NULL if not
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. */
UNIV_INLINE
......@@ -833,11 +838,8 @@ struct buf_pool_struct{
mutex_t mutex; /* mutex protecting the buffer pool
struct and control blocks, except the
read-write lock in them */
byte* frame_mem; /* pointer to the memory area which
was allocated for the frames */
ulint frame_mem_size; /* allocated length of frame_mem
in bytes */
buf_block_t* blocks; /* array of buffer control blocks */
ulint n_chunks; /* number of buffer pool chunks */
buf_chunk_t* chunks; /* buffer pool chunks */
ulint curr_size; /* current pool size in pages */
hash_table_t* page_hash; /* hash table of the file pages */
......
......@@ -42,22 +42,6 @@ buf_pool_get_curr_size(void)
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
ut_dulint_zero if all modified pages have been flushed to disk. */
......@@ -114,8 +98,6 @@ buf_block_get_frame(
buf_block_t* block) /* in: pointer to the control 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_FILE_PAGE)
|| (block->buf_fix_count > 0));
......@@ -133,8 +115,6 @@ buf_block_get_space(
const buf_block_t* block) /* in: pointer to the control 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_ad(block->buf_fix_count > 0);
......@@ -151,8 +131,6 @@ buf_block_get_page_no(
const buf_block_t* block) /* in: pointer to the control 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_ad(block->buf_fix_count > 0);
......
......@@ -94,8 +94,9 @@ ibool
buf_flush_ready_for_replace(
/*========================*/
/* out: TRUE if can replace immediately */
buf_block_t* block); /* in: buffer control block, must be in state
BUF_BLOCK_FILE_PAGE and in the LRU list */
buf_block_t* block); /* in: buffer control block, must
be in state BUF_BLOCK_FILE_PAGE
and in the LRU list */
/**********************************************************************
Validates the flush list. */
......
......@@ -10,6 +10,7 @@ Created 11/17/1995 Heikki Tuuri
#define buf0types_h
typedef struct buf_block_struct buf_block_t;
typedef struct buf_chunk_struct buf_chunk_t;
typedef struct buf_pool_struct buf_pool_t;
/* The 'type' used of a buffer frame */
......
......@@ -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
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_lock_table_size;
......@@ -153,7 +155,6 @@ extern ulong srv_thread_sleep_delay;
extern ulint srv_spin_wait_delay;
extern ibool srv_priority_boost;
extern ulint srv_pool_size;
extern ulint srv_mem_pool_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
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
};
ulint srv_pool_size = ULINT_MAX; /* size in pages; MySQL inits
this to size in kilobytes but
we normalize this to pages in
srv_boot() */
ulong srv_buf_pool_size = ULINT_MAX; /* requested size
in kilobytes */
ulong srv_buf_pool_old_size; /* previously requested size */
ulong srv_buf_pool_curr_size = 0; /* current size
in kilobytes */
ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */
ulint srv_lock_table_size = ULINT_MAX;
......@@ -1233,9 +1234,7 @@ srv_normalize_init_values(void)
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_pool_size;
srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
return(DB_SUCCESS);
}
......
......@@ -1132,7 +1132,7 @@ innobase_start_or_create_for_mysql(void)
}
/* 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
inside InnoDB: this is the 'sync wait array' size, as well as the
......@@ -1147,15 +1147,12 @@ innobase_start_or_create_for_mysql(void)
NetWare. */
srv_max_n_threads = 1000;
#else
if (srv_pool_size >= 1000 * 1024) {
/* Here we still have srv_pool_size counted
in kilobytes (in 4.0 this was in bytes)
srv_boot() converts the value to
pages; if buffer pool is less than 1000 MB,
if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
/* If buffer pool is less than 1000 MB,
assume fewer threads. */
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;
} else {
......@@ -1164,7 +1161,7 @@ innobase_start_or_create_for_mysql(void)
computers */
}
#endif
err = srv_boot(); /* This changes srv_pool_size to units of a page */
err = srv_boot();
if (err != DB_SUCCESS) {
......@@ -1230,7 +1227,7 @@ innobase_start_or_create_for_mysql(void)
fil_init(srv_max_n_open_files);
ret = buf_pool_init(srv_pool_size);
ret = buf_pool_init();
if (ret == NULL) {
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