Commit a687ccdf authored by marko's avatar marko

branches/zip: Minor improvements.

buf_LRU_block_remove_hashed_page(): Return the new state of the block.

Only call buf_LRU_block_free_hashed_page()
if buf_LRU_block_remove_hashed_page() did not return BUF_BLOCK_ZIP_FREE,
that is, the control block was not freed.

buf_LRU_insert_zip_clean(): New function, for inserting a compressed-only
block into buf_pool->zip_clean in the LRU order.

buf_LRU_block_remove_hashed_page(), buf_LRU_free_block():
Add the flag "zip" for controlling if the compressed page of an uncompressed
page should be removed.  For now, assume zip==TRUE.

buf_LRU_get_free_block(): Replace the test for UT_LIST_GET_LEN(buf_pool->free)
with a test for the return value of buf_LRU_get_free_only().  Do not
free zip.data, as it must already have been freed.

buf_flush_insert_into_flush_list(), buf_flush_insert_sorted_into_flush_list():
Remove compressed-only blocks from the buf_pool->zip_clean list.

buf_flush_remove(): Restore compressed-only blocks to
the buf_pool->zip_clean list.

buf_page_init_for_read(): Uncompress compressed-only blocks when possible.
Currently, there cannot be any compressed-only blocks in the buffer pool;
they would be inserted by buf_LRU_free_block(bpage, zip=FALSE).
parent b6711d69
...@@ -165,7 +165,7 @@ buf_buddy_alloc_clean( ...@@ -165,7 +165,7 @@ buf_buddy_alloc_clean(
for (; j--; bpage = UT_LIST_GET_NEXT(list, bpage)) { for (; j--; bpage = UT_LIST_GET_NEXT(list, bpage)) {
if (bpage->zip.ssize != dummy_zip.ssize if (bpage->zip.ssize != dummy_zip.ssize
|| !buf_LRU_free_block(bpage)) { || !buf_LRU_free_block(bpage, FALSE)) {
continue; continue;
} }
...@@ -197,7 +197,8 @@ buf_buddy_alloc_clean( ...@@ -197,7 +197,8 @@ buf_buddy_alloc_clean(
void* ret; void* ret;
if (!buf_LRU_free_block(bpage)) { /* Keep the compressed pages of uncompressed blocks. */
if (!buf_LRU_free_block(bpage, FALSE)) {
continue; continue;
} }
......
...@@ -26,6 +26,7 @@ Created 11/5/1995 Heikki Tuuri ...@@ -26,6 +26,7 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0buf.ic" #include "buf0buf.ic"
#endif #endif
#include "buf0buddy.h"
#include "mem0mem.h" #include "mem0mem.h"
#include "btr0btr.h" #include "btr0btr.h"
#include "fil0fil.h" #include "fil0fil.h"
...@@ -1030,7 +1031,7 @@ buf_pool_shrink( ...@@ -1030,7 +1031,7 @@ buf_pool_shrink(
buf_LRU_make_block_old(&block->page); buf_LRU_make_block_old(&block->page);
dirty++; dirty++;
} else if (!buf_LRU_free_block(&block->page)) { } else if (!buf_LRU_free_block(&block->page, TRUE)) {
nonfree++; nonfree++;
} }
...@@ -1938,6 +1939,7 @@ buf_page_init_for_read( ...@@ -1938,6 +1939,7 @@ buf_page_init_for_read(
ulint offset) /* in: page number */ ulint offset) /* in: page number */
{ {
buf_block_t* block; buf_block_t* block;
buf_page_t* bpage;
mtr_t mtr; mtr_t mtr;
ut_ad(buf_pool); ut_ad(buf_pool);
...@@ -1972,11 +1974,78 @@ buf_page_init_for_read( ...@@ -1972,11 +1974,78 @@ buf_page_init_for_read(
if (fil_tablespace_deleted_or_being_deleted_in_mem( if (fil_tablespace_deleted_or_being_deleted_in_mem(
space, tablespace_version)) { space, tablespace_version)) {
*err = DB_TABLESPACE_DELETED; *err = DB_TABLESPACE_DELETED;
goto err_exit;
} }
if (*err == DB_TABLESPACE_DELETED bpage = buf_page_hash_get(space, offset);
|| NULL != buf_page_hash_get(space, offset)) {
if (UNIV_LIKELY_NULL(bpage)) {
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
ut_a(page_zip_get_size(&bpage->zip) == zip_size);
if (bpage->buf_fix_count
|| buf_page_get_io_fix(bpage)
!= BUF_IO_NONE) {
goto err_exit;
}
/* Move the compressed page from bpage to block,
and uncompress it. */
buf_buddy_free(block->page.zip.data, zip_size);
mutex_enter(&buf_pool->zip_mutex);
memcpy(&block->page, bpage, sizeof *bpage);
block->page.state = BUF_BLOCK_FILE_PAGE;
buf_relocate(bpage, &block->page);
if (buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE) {
UT_LIST_REMOVE(list, buf_pool->zip_clean,
bpage);
} else {
/* Relocate buf_pool->flush_list. */
buf_page_t* b;
b = UT_LIST_GET_PREV(list, bpage);
UT_LIST_REMOVE(list, buf_pool->flush_list,
bpage);
if (b) {
UT_LIST_INSERT_AFTER(
list, buf_pool->flush_list, b,
&block->page);
} else {
UT_LIST_ADD_FIRST(
list, buf_pool->flush_list,
&block->page);
}
}
bpage->zip.data = NULL;
page_zip_set_size(&bpage->zip, 0);
buf_buddy_free(bpage, sizeof *bpage);
mutex_exit(&buf_pool->zip_mutex);
break;
case BUF_BLOCK_FILE_PAGE:
break;
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
ut_error;
break;
}
err_exit:
/* The page belongs to a space which has been /* The page belongs to a space which has been
deleted or is being deleted, or the page is deleted or is being deleted, or the page is
already in buf_pool, return */ already in buf_pool, return */
......
...@@ -55,13 +55,29 @@ buf_flush_insert_into_flush_list( ...@@ -55,13 +55,29 @@ buf_flush_insert_into_flush_list(
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
ut_a(buf_page_in_file(bpage));
ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL) ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL)
|| (UT_LIST_GET_FIRST(buf_pool->flush_list)->oldest_modification || (UT_LIST_GET_FIRST(buf_pool->flush_list)->oldest_modification
<= bpage->oldest_modification)); <= bpage->oldest_modification));
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
mutex_enter(&buf_pool->zip_mutex);
buf_page_set_state(bpage, BUF_BLOCK_ZIP_DIRTY);
mutex_exit(&buf_pool->zip_mutex);
UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
/* fall through */
case BUF_BLOCK_ZIP_DIRTY:
case BUF_BLOCK_FILE_PAGE:
UT_LIST_ADD_FIRST(list, buf_pool->flush_list, bpage); UT_LIST_ADD_FIRST(list, buf_pool->flush_list, bpage);
break;
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
ut_error;
return;
}
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_flush_validate_low()); ut_a(buf_flush_validate_low());
...@@ -85,6 +101,25 @@ buf_flush_insert_sorted_into_flush_list( ...@@ -85,6 +101,25 @@ buf_flush_insert_sorted_into_flush_list(
ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
mutex_enter(&buf_pool->zip_mutex);
buf_page_set_state(bpage, BUF_BLOCK_ZIP_DIRTY);
mutex_exit(&buf_pool->zip_mutex);
UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
/* fall through */
case BUF_BLOCK_ZIP_DIRTY:
case BUF_BLOCK_FILE_PAGE:
break;
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
ut_error;
return;
}
prev_b = NULL; prev_b = NULL;
b = UT_LIST_GET_FIRST(buf_pool->flush_list); b = UT_LIST_GET_FIRST(buf_pool->flush_list);
...@@ -202,7 +237,9 @@ buf_flush_remove( ...@@ -202,7 +237,9 @@ buf_flush_remove(
mutex_enter(&buf_pool->zip_mutex); mutex_enter(&buf_pool->zip_mutex);
buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE); buf_page_set_state(bpage, BUF_BLOCK_ZIP_PAGE);
mutex_exit(&buf_pool->zip_mutex); mutex_exit(&buf_pool->zip_mutex);
/* fall through */ UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
buf_LRU_insert_zip_clean(bpage);
break;
case BUF_BLOCK_FILE_PAGE: case BUF_BLOCK_FILE_PAGE:
UT_LIST_REMOVE(list, buf_pool->flush_list, bpage); UT_LIST_REMOVE(list, buf_pool->flush_list, bpage);
break; break;
......
...@@ -49,15 +49,20 @@ frames in the buffer pool, we set this to TRUE */ ...@@ -49,15 +49,20 @@ frames in the buffer pool, we set this to TRUE */
ibool buf_lru_switched_on_innodb_mon = FALSE; ibool buf_lru_switched_on_innodb_mon = FALSE;
/********************************************************************** /**********************************************************************
Takes a block out of the LRU list and page hash table and sets the block Takes a block out of the LRU list and page hash table. */
state to BUF_BLOCK_REMOVE_HASH. */
static static
void enum buf_page_state
buf_LRU_block_remove_hashed_page( buf_LRU_block_remove_hashed_page(
/*=============================*/ /*=============================*/
buf_page_t* bpage); /* in: block, must contain a file page and /* out: the new state of the block
(BUF_BLOCK_ZIP_FREE if the state was
BUF_BLOCK_ZIP_PAGE, or BUF_BLOCK_REMOVE_HASH
otherwise) */
buf_page_t* bpage, /* in: block, must contain a file page and
be in a state where it can be freed; there be in a state where it can be freed; there
may or may not be a hash index to the page */ may or may not be a hash index to the page */
ibool zip); /* in: TRUE if should remove also the
compressed page of an uncompressed page */
/********************************************************************** /**********************************************************************
Puts a file page whose has no hash index to the free list. */ Puts a file page whose has no hash index to the free list. */
static static
...@@ -139,9 +144,11 @@ buf_LRU_invalidate_tablespace( ...@@ -139,9 +144,11 @@ buf_LRU_invalidate_tablespace(
} }
/* Remove from the LRU list */ /* Remove from the LRU list */
buf_LRU_block_remove_hashed_page(bpage); if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
!= BUF_BLOCK_ZIP_FREE) {
buf_LRU_block_free_hashed_page(bpage); buf_LRU_block_free_hashed_page(bpage);
} }
}
next_page: next_page:
mutex_exit(block_mutex); mutex_exit(block_mutex);
bpage = prev_bpage; bpage = prev_bpage;
...@@ -191,6 +198,40 @@ buf_LRU_get_recent_limit(void) ...@@ -191,6 +198,40 @@ buf_LRU_get_recent_limit(void)
return(limit); return(limit);
} }
/************************************************************************
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
void
buf_LRU_insert_zip_clean(
/*=====================*/
buf_page_t* bpage) /* in: pointer to the block in question */
{
buf_page_t* b;
#ifdef UNIV_SYNC_DEBUG
ut_a(mutex_own(&buf_pool->mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
/* Find the first successor of bpage in the LRU list
that is in the zip_clean list. */
b = bpage;
do {
b = UT_LIST_GET_NEXT(LRU, b);
} while (b && buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE);
/* Insert bpage before b, i.e., after the predecessor of b. */
if (b) {
b = UT_LIST_GET_PREV(list, b);
}
if (b) {
UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, bpage);
} else {
UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
}
}
/********************************************************************** /**********************************************************************
Try to free a block. */ Try to free a block. */
...@@ -198,7 +239,9 @@ ibool ...@@ -198,7 +239,9 @@ ibool
buf_LRU_free_block( buf_LRU_free_block(
/*===============*/ /*===============*/
/* out: TRUE if freed */ /* out: TRUE if freed */
buf_page_t* bpage) /* in: block to be freed */ buf_page_t* bpage, /* in: block to be freed */
ibool zip) /* in: TRUE if should remove also the
compressed page of an uncompressed page */
{ {
mutex_t* block_mutex = buf_page_get_mutex(bpage); mutex_t* block_mutex = buf_page_get_mutex(bpage);
...@@ -223,12 +266,8 @@ buf_LRU_free_block( ...@@ -223,12 +266,8 @@ buf_LRU_free_block(
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
buf_LRU_block_remove_hashed_page(bpage); if (buf_LRU_block_remove_hashed_page(bpage, zip)
!= BUF_BLOCK_ZIP_FREE) {
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_REMOVE_HASH:
/* The state was changed from BUF_BLOCK_FILE_PAGE
in buf_LRU_block_remove_hashed_page(bpage). */
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
mutex_exit(block_mutex); mutex_exit(block_mutex);
...@@ -241,22 +280,6 @@ buf_LRU_free_block( ...@@ -241,22 +280,6 @@ buf_LRU_free_block(
mutex_enter(block_mutex); mutex_enter(block_mutex);
buf_LRU_block_free_hashed_page(bpage); buf_LRU_block_free_hashed_page(bpage);
break;
case BUF_BLOCK_ZIP_PAGE:
ut_ad(!bpage->in_free_list);
ut_ad(!bpage->in_LRU_list);
UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
buf_buddy_free(bpage->zip.data,
page_zip_get_size(&bpage->zip));
buf_buddy_free(bpage, sizeof(*bpage));
break;
default:
ut_error;
break;
} }
return(TRUE); return(TRUE);
...@@ -290,7 +313,7 @@ buf_LRU_search_and_free_block( ...@@ -290,7 +313,7 @@ buf_LRU_search_and_free_block(
mutex_t* block_mutex = buf_page_get_mutex(bpage); mutex_t* block_mutex = buf_page_get_mutex(bpage);
mutex_enter(block_mutex); mutex_enter(block_mutex);
freed = buf_LRU_free_block(bpage); freed = buf_LRU_free_block(bpage, n_iterations > 10);
mutex_exit(block_mutex); mutex_exit(block_mutex);
if (freed) { if (freed) {
...@@ -496,30 +519,24 @@ buf_LRU_get_free_block( ...@@ -496,30 +519,24 @@ buf_LRU_get_free_block(
} }
/* If there is a block in the free list, take it */ /* If there is a block in the free list, take it */
if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
block = buf_LRU_get_free_only(); block = buf_LRU_get_free_only();
ut_a(block); /* We tested that buf_pool->free is nonempty. */ if (block) {
if (buf_block_get_zip_size(block) != zip_size) {
page_zip_set_size(&block->page.zip, zip_size);
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
block->page.zip.m_start = block->page.zip.m_start =
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
block->page.zip.m_end = block->page.zip.m_end =
block->page.zip.m_nonempty = block->page.zip.m_nonempty =
block->page.zip.n_blobs = 0; block->page.zip.n_blobs = 0;
if (block->page.zip.data) {
ut_free(block->page.zip.data);
}
if (zip_size) { if (zip_size) {
page_zip_set_size(&block->page.zip, zip_size);
/* TODO: allocate zip from an aligned pool */ /* TODO: allocate zip from an aligned pool */
block->page.zip.data = ut_malloc(zip_size); block->page.zip.data = ut_malloc(zip_size);
} else { } else {
page_zip_set_size(&block->page.zip, 0);
block->page.zip.data = NULL; block->page.zip.data = NULL;
} }
}
mutex_exit(&(buf_pool->mutex)); mutex_exit(&(buf_pool->mutex));
...@@ -951,15 +968,20 @@ buf_LRU_block_free_non_file_page( ...@@ -951,15 +968,20 @@ buf_LRU_block_free_non_file_page(
} }
/********************************************************************** /**********************************************************************
Takes a block out of the LRU list and page hash table and sets the block Takes a block out of the LRU list and page hash table. */
state to BUF_BLOCK_REMOVE_HASH. */
static static
void enum buf_page_state
buf_LRU_block_remove_hashed_page( buf_LRU_block_remove_hashed_page(
/*=============================*/ /*=============================*/
buf_page_t* bpage) /* in: block, must contain a file page and /* out: the new state of the block
(BUF_BLOCK_ZIP_FREE if the state was
BUF_BLOCK_ZIP_PAGE, or BUF_BLOCK_REMOVE_HASH
otherwise) */
buf_page_t* bpage, /* in: block, must contain a file page and
be in a state where it can be freed; there be in a state where it can be freed; there
may or may not be a hash index to the page */ may or may not be a hash index to the page */
ibool zip) /* in: TRUE if should remove also the
compressed page of an uncompressed page */
{ {
const buf_page_t* hashed_bpage; const buf_page_t* hashed_bpage;
ut_ad(bpage); ut_ad(bpage);
...@@ -982,8 +1004,14 @@ buf_LRU_block_remove_hashed_page( ...@@ -982,8 +1004,14 @@ buf_LRU_block_remove_hashed_page(
break; break;
case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_ZIP_PAGE:
break; break;
default: case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_ZIP_DIRTY:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
ut_error; ut_error;
break;
} }
hashed_bpage = buf_page_hash_get(bpage->space, bpage->offset); hashed_bpage = buf_page_hash_get(bpage->space, bpage->offset);
...@@ -1018,6 +1046,8 @@ buf_LRU_block_remove_hashed_page( ...@@ -1018,6 +1046,8 @@ buf_LRU_block_remove_hashed_page(
bpage); bpage);
switch (buf_page_get_state(bpage)) { switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE: case BUF_BLOCK_ZIP_PAGE:
ut_ad(!bpage->in_free_list);
ut_ad(!bpage->in_LRU_list);
ut_a(bpage->zip.data); ut_a(bpage->zip.data);
ut_a(buf_page_get_zip_size(bpage)); ut_a(buf_page_get_zip_size(bpage));
memset(bpage->zip.data + FIL_PAGE_OFFSET, 0xff, 4); memset(bpage->zip.data + FIL_PAGE_OFFSET, 0xff, 4);
...@@ -1030,10 +1060,27 @@ buf_LRU_block_remove_hashed_page( ...@@ -1030,10 +1060,27 @@ buf_LRU_block_remove_hashed_page(
memset(((buf_block_t*) bpage)->frame memset(((buf_block_t*) bpage)->frame
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4); + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4);
buf_page_set_state(bpage, BUF_BLOCK_REMOVE_HASH); buf_page_set_state(bpage, BUF_BLOCK_REMOVE_HASH);
if (bpage->zip.data) {
/* Free the compressed page. */
ut_free(bpage->zip.data);
bpage->zip.data = NULL;
page_zip_set_size(&bpage->zip, 0);
}
return(BUF_BLOCK_REMOVE_HASH);
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_ZIP_DIRTY:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
break; break;
default:
ut_error;
} }
ut_error;
return(BUF_BLOCK_ZIP_FREE);
} }
/********************************************************************** /**********************************************************************
......
...@@ -65,6 +65,13 @@ ulint ...@@ -65,6 +65,13 @@ ulint
buf_LRU_get_recent_limit(void); buf_LRU_get_recent_limit(void);
/*==========================*/ /*==========================*/
/* out: the limit; zero if could not determine it */ /* out: the limit; zero if could not determine it */
/************************************************************************
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
void
buf_LRU_insert_zip_clean(
/*=====================*/
buf_page_t* bpage); /* in: pointer to the block in question */
/********************************************************************** /**********************************************************************
Try to free a block. */ Try to free a block. */
...@@ -72,7 +79,9 @@ ibool ...@@ -72,7 +79,9 @@ ibool
buf_LRU_free_block( buf_LRU_free_block(
/*===============*/ /*===============*/
/* out: TRUE if freed */ /* out: TRUE if freed */
buf_page_t* block); /* in: block to be freed */ buf_page_t* block, /* in: block to be freed */
ibool zip); /* in: TRUE if should remove also the
compressed page of an uncompressed page */
/********************************************************************** /**********************************************************************
Look for a replaceable block from the end of the LRU list and put it to Look for a replaceable block from the end of the LRU list and put it to
the free list if found. */ the free list if found. */
......
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