mariadb/include/buf0buf.ic

1054 lines
26 KiB
Text
Raw Normal View History

2005-10-27 07:29:40 +00:00
/******************************************************
The database buffer buf_pool
(c) 1995 Innobase Oy
Created 11/5/1995 Heikki Tuuri
*******************************************************/
#include "buf0flu.h"
#include "buf0lru.h"
#include "buf0rea.h"
#include "mtr0mtr.h"
/************************************************************************
Reads the freed_page_clock of a buffer block. */
UNIV_INLINE
ulint
buf_page_get_freed_page_clock(
/*==========================*/
/* out: freed_page_clock */
const buf_page_t* bpage) /* in: block */
{
/* This is sometimes read without holding buf_pool_mutex. */
return(bpage->freed_page_clock);
}
/************************************************************************
Reads the freed_page_clock of a buffer block. */
UNIV_INLINE
ulint
buf_block_get_freed_page_clock(
/*===========================*/
/* out: freed_page_clock */
const buf_block_t* block) /* in: block */
{
return(buf_page_get_freed_page_clock(&block->page));
}
2005-10-27 07:29:40 +00:00
/************************************************************************
Recommends a move of a block to the start of the LRU list if there is danger
of dropping from the buffer pool. NOTE: does not reserve the buffer pool
mutex. */
2005-10-27 07:29:40 +00:00
UNIV_INLINE
ibool
buf_page_peek_if_too_old(
/*=====================*/
/* out: TRUE if should be made
younger */
const buf_page_t* bpage) /* in: block to make younger */
2005-10-27 07:29:40 +00:00
{
return(buf_pool->freed_page_clock
>= buf_page_get_freed_page_clock(bpage)
+ 1 + (buf_pool->curr_size / 4));
2005-10-27 07:29:40 +00:00
}
/*************************************************************************
Gets the current size of buffer buf_pool in bytes. */
2005-10-27 07:29:40 +00:00
UNIV_INLINE
ulint
buf_pool_get_curr_size(void)
/*========================*/
/* out: size in bytes */
{
return(buf_pool->curr_size * UNIV_PAGE_SIZE);
}
2005-10-27 07:29:40 +00:00
/************************************************************************
Gets the smallest oldest_modification lsn for any page in the pool. Returns
zero if all modified pages have been flushed to disk. */
2005-10-27 07:29:40 +00:00
UNIV_INLINE
ib_uint64_t
2005-10-27 07:29:40 +00:00
buf_pool_get_oldest_modification(void)
/*==================================*/
/* out: oldest modification in pool,
zero if none */
2005-10-27 07:29:40 +00:00
{
buf_page_t* bpage;
ib_uint64_t lsn;
buf_pool_mutex_enter();
2005-10-27 07:29:40 +00:00
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
2005-10-27 07:29:40 +00:00
if (bpage == NULL) {
lsn = 0;
2005-10-27 07:29:40 +00:00
} else {
ut_ad(bpage->in_flush_list);
lsn = bpage->oldest_modification;
2005-10-27 07:29:40 +00:00
}
buf_pool_mutex_exit();
2005-10-27 07:29:40 +00:00
/* The returned answer may be out of date: the flush_list can
change after the mutex has been released. */
2005-10-27 07:29:40 +00:00
return(lsn);
}
/***********************************************************************
Increments the buf_pool clock by one and returns its new value. Remember
that in the 32 bit version the clock wraps around at 4 billion! */
UNIV_INLINE
ulint
buf_pool_clock_tic(void)
/*====================*/
/* out: new clock value */
{
ut_ad(buf_pool_mutex_own());
2005-10-27 07:29:40 +00:00
buf_pool->ulint_clock++;
return(buf_pool->ulint_clock);
}
/*************************************************************************
Gets the state of a block. */
UNIV_INLINE
enum buf_page_state
buf_page_get_state(
/*===============*/
/* out: state */
const buf_page_t* bpage) /* in: pointer to the control block */
{
enum buf_page_state state = (enum buf_page_state) bpage->state;
#ifdef UNIV_DEBUG
switch (state) {
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_FILE_PAGE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
break;
default:
ut_error;
}
#endif /* UNIV_DEBUG */
return(state);
}
/*************************************************************************
Gets the state of a block. */
UNIV_INLINE
enum buf_page_state
buf_block_get_state(
/*================*/
/* out: state */
const buf_block_t* block) /* in: pointer to the control block */
{
return(buf_page_get_state(&block->page));
}
/*************************************************************************
Sets the state of a block. */
UNIV_INLINE
void
buf_page_set_state(
/*===============*/
buf_page_t* bpage, /* in/out: pointer to control block */
enum buf_page_state state) /* in: state */
{
#ifdef UNIV_DEBUG
enum buf_page_state old_state = buf_page_get_state(bpage);
switch (old_state) {
case BUF_BLOCK_ZIP_FREE:
ut_error;
break;
case BUF_BLOCK_ZIP_PAGE:
ut_a(state == BUF_BLOCK_ZIP_DIRTY);
break;
case BUF_BLOCK_ZIP_DIRTY:
ut_a(state == BUF_BLOCK_ZIP_PAGE);
break;
case BUF_BLOCK_NOT_USED:
ut_a(state == BUF_BLOCK_READY_FOR_USE);
break;
case BUF_BLOCK_READY_FOR_USE:
ut_a(state == BUF_BLOCK_MEMORY
|| state == BUF_BLOCK_FILE_PAGE
|| state == BUF_BLOCK_NOT_USED);
break;
case BUF_BLOCK_MEMORY:
ut_a(state == BUF_BLOCK_NOT_USED);
break;
case BUF_BLOCK_FILE_PAGE:
ut_a(state == BUF_BLOCK_NOT_USED
|| state == BUF_BLOCK_REMOVE_HASH);
break;
case BUF_BLOCK_REMOVE_HASH:
ut_a(state == BUF_BLOCK_MEMORY);
break;
}
#endif /* UNIV_DEBUG */
bpage->state = state;
ut_ad(buf_page_get_state(bpage) == state);
}
/*************************************************************************
Sets the state of a block. */
UNIV_INLINE
void
buf_block_set_state(
/*================*/
buf_block_t* block, /* in/out: pointer to control block */
enum buf_page_state state) /* in: state */
{
buf_page_set_state(&block->page, state);
}
/*************************************************************************
Determines if a block is mapped to a tablespace. */
UNIV_INLINE
ibool
buf_page_in_file(
/*=============*/
/* out: TRUE if mapped */
const buf_page_t* bpage) /* in: pointer to control block */
{
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_FREE:
/* This is a free page in buf_pool->zip_free[].
Such pages should only be accessed by the buddy allocator. */
ut_error;
break;
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
case BUF_BLOCK_FILE_PAGE:
return(TRUE);
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
break;
}
return(FALSE);
}
branches/zip: Improve the LRU algorithm with a separate unzip_LRU list of blocks that contains uncompressed and compressed frames. This patch was designed by Heikki and Inaam, implemented by Inaam, and refined and reviewed by Marko and Sunny. buf_buddy_n_frames, buf_buddy_min_n_frames, buf_buddy_max_n_frames: Remove. buf_page_belongs_to_unzip_LRU(): New predicate: bpage->zip.data && buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE. buf_pool_t, buf_block_t: Add the linked list unzip_LRU. A block in the regular LRU list is in unzip_LRU iff buf_page_belongs_to_unzip_LRU() holds. buf_LRU_free_block(): Add a third return value to refine the case "cannot free the block". buf_LRU_search_and_free_block(): Update the documentation to reflect the implementation. buf_LRU_stat_t, buf_LRU_stat_cur, buf_LRU_stat_sum, buf_LRU_stat_arr[]: Statistics for the unzip_LRU algorithm. buf_LRU_stat_update(): New function: Update the statistics. Called once per second by srv_error_monitor_thread(). buf_LRU_validate(): Validate the unzip_LRU list as well. buf_LRU_evict_from_unzip_LRU(): New predicate: Use the unzip_LRU before falling back to the regular LRU? buf_LRU_free_from_unzip_LRU_list(), buf_LRU_free_from_common_LRU_list(): Subfunctions of buf_LRU_search_and_free_block(). buf_LRU_search_and_free_block(): Reimplement. Try to evict an uncompressed page from the unzip_LRU list before falling back to evicting an entire block from the common LRU list. buf_unzip_LRU_remove_block_if_needed(): New function. buf_unzip_LRU_add_block(): New function: Add a block to the unzip_LRU list.
2008-03-03 12:48:38 +00:00
/*************************************************************************
Determines if a block should be on unzip_LRU list. */
UNIV_INLINE
ibool
buf_page_belongs_to_unzip_LRU(
/*==========================*/
/* out: TRUE if block belongs
to unzip_LRU */
const buf_page_t* bpage) /* in: pointer to control block */
{
ut_ad(buf_page_in_file(bpage));
return(bpage->zip.data
&& buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
}
/*************************************************************************
Determine the approximate LRU list position of a block. */
UNIV_INLINE
ulint
buf_page_get_LRU_position(
/*======================*/
/* out: LRU list position */
const buf_page_t* bpage) /* in: control block */
{
ut_ad(buf_page_in_file(bpage));
ut_ad(buf_pool_mutex_own());
return(bpage->LRU_position);
}
/*************************************************************************
Gets the mutex of a block. */
UNIV_INLINE
mutex_t*
buf_page_get_mutex(
/*===============*/
/* out: pointer to mutex
protecting bpage */
const buf_page_t* bpage) /* in: pointer to control block */
{
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_FREE:
ut_error;
branches/zip: Fix most MSVC (Windows) compilation warnings. lock_get_table(), locks_row_eq_lock(), buf_page_get_mutex(): Add return after ut_error. On Windows, ut_error is not declared as "noreturn". Add explicit type casts when assigning ulint to byte to get rid of "possible loss of precision" warnings. struct i_s_table_cache_struct: Declare rows_used, rows_allocd as ulint instead of ullint. 32 bits should be enough. fill_innodb_trx_from_cache(), i_s_zip_fill_low(): Cast 64-bit unsigned integers to longlong when calling Field::store(longlong, bool is_unsigned). Otherwise, the compiler would implicitly convert them to double and invoke Field::store(double) instead. recv_truncate_group(), recv_copy_group(), recv_calc_lsn_on_data_add(): Cast ib_uint64_t expressions to ulint to get rid of "possible loss of precision" warnings. (There should not be any loss of precision in these cases.) log_close(), log_checkpoint_margin(): Declare some variables as ib_uint64_t instead of ulint, so that there won't be any potential loss of precision. mach_write_ull(): Cast the second argument of mach_write_to_4() to ulint. OS_FILE_FROM_FD(): Cast the return value of _get_osfhandle() to HANDLE. row_merge_dict_table_get_index(): Cast the parameter of mem_free() to (void*) in order to get rid of the bogus MSVC warning C4090, which has been reported as MSVC bug 101661: <http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101661> row_mysql_read_blob_ref(): To get rid of a bogus MSVC warning C4090, drop a const qualifier.
2008-03-04 08:57:07 +00:00
return(NULL);
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
return(&buf_pool_zip_mutex);
default:
return(&((buf_block_t*) bpage)->mutex);
}
}
/*************************************************************************
Get the flush type of a page. */
UNIV_INLINE
enum buf_flush
buf_page_get_flush_type(
/*====================*/
/* out: flush type */
const buf_page_t* bpage) /* in: buffer page */
{
enum buf_flush flush_type = (enum buf_flush) bpage->flush_type;
#ifdef UNIV_DEBUG
switch (flush_type) {
case BUF_FLUSH_LRU:
case BUF_FLUSH_SINGLE_PAGE:
case BUF_FLUSH_LIST:
return(flush_type);
case BUF_FLUSH_N_TYPES:
break;
}
ut_error;
#endif /* UNIV_DEBUG */
return(flush_type);
}
/*************************************************************************
Set the flush type of a page. */
UNIV_INLINE
void
buf_page_set_flush_type(
/*====================*/
buf_page_t* bpage, /* in: buffer page */
enum buf_flush flush_type) /* in: flush type */
{
bpage->flush_type = flush_type;
ut_ad(buf_page_get_flush_type(bpage) == flush_type);
}
/*************************************************************************
Map a block to a file page. */
UNIV_INLINE
void
buf_block_set_file_page(
/*====================*/
buf_block_t* block, /* in/out: pointer to control block */
ulint space, /* in: tablespace id */
ulint page_no)/* in: page number */
{
buf_block_set_state(block, BUF_BLOCK_FILE_PAGE);
block->page.space = space;
block->page.offset = page_no;
}
/*************************************************************************
Gets the io_fix state of a block. */
UNIV_INLINE
enum buf_io_fix
buf_page_get_io_fix(
/*================*/
/* out: io_fix state */
const buf_page_t* bpage) /* in: pointer to the control block */
{
enum buf_io_fix io_fix = (enum buf_io_fix) bpage->io_fix;
#ifdef UNIV_DEBUG
switch (io_fix) {
case BUF_IO_NONE:
case BUF_IO_READ:
case BUF_IO_WRITE:
return(io_fix);
}
ut_error;
#endif /* UNIV_DEBUG */
return(io_fix);
}
/*************************************************************************
Gets the io_fix state of a block. */
UNIV_INLINE
enum buf_io_fix
buf_block_get_io_fix(
/*================*/
/* out: io_fix state */
const buf_block_t* block) /* in: pointer to the control block */
{
return(buf_page_get_io_fix(&block->page));
}
/*************************************************************************
Sets the io_fix state of a block. */
UNIV_INLINE
void
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());
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
bpage->io_fix = io_fix;
ut_ad(buf_page_get_io_fix(bpage) == io_fix);
}
/*************************************************************************
Sets the io_fix state of a block. */
UNIV_INLINE
void
buf_block_set_io_fix(
/*=================*/
buf_block_t* block, /* in/out: control block */
enum buf_io_fix io_fix) /* in: io_fix state */
{
buf_page_set_io_fix(&block->page, io_fix);
}
/************************************************************************
Determine if a buffer block can be relocated in memory. The block
can be dirty, but it must not be I/O-fixed or bufferfixed. */
UNIV_INLINE
ibool
buf_page_can_relocate(
/*==================*/
const buf_page_t* bpage) /* control block being relocated */
{
ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->in_LRU_list);
return(buf_page_get_io_fix(bpage) == BUF_IO_NONE
&& bpage->buf_fix_count == 0);
}
/*************************************************************************
Determine if a block has been flagged old. */
UNIV_INLINE
ibool
buf_page_is_old(
/*============*/
/* out: TRUE if old */
const buf_page_t* bpage) /* in: control block */
{
ut_ad(buf_page_in_file(bpage));
ut_ad(buf_pool_mutex_own());
return(bpage->old);
}
/*************************************************************************
Flag a block old. */
UNIV_INLINE
void
buf_page_set_old(
/*=============*/
buf_page_t* bpage, /* in/out: control block */
ibool old) /* in: old */
{
ut_a(buf_page_in_file(bpage));
ut_ad(buf_pool_mutex_own());
ut_ad(bpage->in_LRU_list);
#ifdef UNIV_LRU_DEBUG
if (UT_LIST_GET_PREV(LRU, bpage) && UT_LIST_GET_NEXT(LRU, bpage)
&& UT_LIST_GET_PREV(LRU, bpage)->old
== UT_LIST_GET_NEXT(LRU, bpage)->old) {
ut_a(UT_LIST_GET_PREV(LRU, bpage)->old == old);
}
#endif /* UNIV_LRU_DEBUG */
bpage->old = old;
}
/*************************************************************************
Determine if a block has been accessed in the buffer pool. */
UNIV_INLINE
ibool
buf_page_is_accessed(
/*=================*/
/* out: TRUE if accessed */
const buf_page_t* bpage) /* in: control block */
{
ut_ad(buf_page_in_file(bpage));
return(bpage->accessed);
}
/*************************************************************************
Flag a block accessed. */
UNIV_INLINE
void
buf_page_set_accessed(
/*==================*/
buf_page_t* bpage, /* in/out: control block */
ibool accessed) /* in: accessed */
{
ut_a(buf_page_in_file(bpage));
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
bpage->accessed = accessed;
}
/*************************************************************************
Gets the buf_block_t handle of a buffered file block if an uncompressed
page frame exists, or NULL. */
UNIV_INLINE
buf_block_t*
buf_page_get_block(
/*===============*/
/* out: control block, or NULL */
buf_page_t* bpage) /* in: control block, or NULL */
{
if (UNIV_LIKELY(bpage != NULL)) {
ut_ad(buf_page_in_file(bpage));
if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
return((buf_block_t*) bpage);
}
}
return(NULL);
}
#ifdef UNIV_DEBUG
2005-10-27 07:29:40 +00:00
/*************************************************************************
Gets a pointer to the memory frame of a block. */
UNIV_INLINE
buf_frame_t*
buf_block_get_frame(
/*================*/
/* out: pointer to the frame */
const buf_block_t* block) /* in: pointer to the control block */
2005-10-27 07:29:40 +00:00
{
ut_ad(block);
switch (buf_block_get_state(block)) {
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
case BUF_BLOCK_NOT_USED:
ut_error;
break;
case BUF_BLOCK_FILE_PAGE:
ut_a(block->page.buf_fix_count > 0);
/* fall through */
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
goto ok;
}
ut_error;
ok:
return((buf_frame_t*) block->frame);
}
#endif /* UNIV_DEBUG */
2005-10-27 07:29:40 +00:00
/*************************************************************************
Gets the space id of a block. */
UNIV_INLINE
ulint
buf_page_get_space(
/*===============*/
/* out: space id */
const buf_page_t* bpage) /* in: pointer to the control block */
{
ut_ad(bpage);
ut_a(buf_page_in_file(bpage));
return(bpage->space);
}
2005-10-27 07:29:40 +00:00
/*************************************************************************
Gets the space id of a block. */
UNIV_INLINE
ulint
buf_block_get_space(
/*================*/
/* out: space id */
const buf_block_t* block) /* in: pointer to the control block */
2005-10-27 07:29:40 +00:00
{
ut_ad(block);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
return(block->page.space);
}
2005-10-27 07:29:40 +00:00
/*************************************************************************
Gets the page number of a block. */
UNIV_INLINE
ulint
buf_page_get_page_no(
/*=================*/
/* out: page number */
const buf_page_t* bpage) /* in: pointer to the control block */
{
ut_ad(bpage);
ut_a(buf_page_in_file(bpage));
return(bpage->offset);
}
2005-10-27 07:29:40 +00:00
/*************************************************************************
Gets the page number of a block. */
UNIV_INLINE
ulint
buf_block_get_page_no(
/*==================*/
/* out: page number */
const buf_block_t* block) /* in: pointer to the control block */
2005-10-27 07:29:40 +00:00
{
ut_ad(block);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
return(block->page.offset);
}
2005-10-27 07:29:40 +00:00
/*************************************************************************
Gets the compressed page size of a block. */
UNIV_INLINE
ulint
buf_page_get_zip_size(
/*==================*/
/* out: compressed page size, or 0 */
const buf_page_t* bpage) /* in: pointer to the control block */
{
return(bpage->zip.ssize ? 512 << bpage->zip.ssize : 0);
}
/*************************************************************************
Gets the compressed page size of a block. */
UNIV_INLINE
ulint
buf_block_get_zip_size(
/*===================*/
/* out: compressed page size, or 0 */
const buf_block_t* block) /* in: pointer to the control block */
{
return(block->page.zip.ssize ? 512 << block->page.zip.ssize : 0);
}
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
/*************************************************************************
Gets the compressed page descriptor corresponding to an uncompressed page
if applicable. */
UNIV_INLINE
const page_zip_des_t*
buf_frame_get_page_zip(
/*===================*/
/* out: compressed page descriptor, or NULL */
const byte* ptr) /* in: pointer to the page */
{
return(buf_block_get_page_zip(buf_block_align(ptr)));
}
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
2005-10-27 07:29:40 +00:00
/**************************************************************************
Gets the space id, page offset, and byte offset within page of a
pointer pointing to a buffer frame containing a file page. */
UNIV_INLINE
void
buf_ptr_get_fsp_addr(
/*=================*/
const void* ptr, /* in: pointer to a buffer frame */
2005-10-27 07:29:40 +00:00
ulint* space, /* out: space id */
fil_addr_t* addr) /* out: page offset and byte offset */
{
const page_t* page = (const page_t*) ut_align_down(ptr,
UNIV_PAGE_SIZE);
2005-10-27 07:29:40 +00:00
*space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
addr->page = mach_read_from_4(page + FIL_PAGE_OFFSET);
addr->boffset = ut_align_offset(ptr, UNIV_PAGE_SIZE);
2005-10-27 07:29:40 +00:00
}
/**************************************************************************
Gets the hash value of the page the pointer is pointing to. This can be used
in searches in the lock hash table. */
UNIV_INLINE
ulint
buf_block_get_lock_hash_val(
2005-10-27 07:29:40 +00:00
/*========================*/
/* out: lock hash value */
const buf_block_t* block) /* in: block */
2005-10-27 07:29:40 +00:00
{
return(block->lock_hash_val);
}
/************************************************************************
Allocates a buffer block. */
UNIV_INLINE
buf_block_t*
buf_block_alloc(
/*============*/
/* out, own: the allocated block,
in state BUF_BLOCK_MEMORY */
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
void
buf_block_free(
/*===========*/
buf_block_t* block) /* in, own: block to be freed */
{
buf_pool_mutex_enter();
mutex_enter(&block->mutex);
ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
buf_LRU_block_free_non_file_page(block);
mutex_exit(&block->mutex);
buf_pool_mutex_exit();
}
2005-10-27 07:29:40 +00:00
/*************************************************************************
Copies contents of a buffer frame to a given buffer. */
UNIV_INLINE
byte*
buf_frame_copy(
/*===========*/
/* out: buf */
byte* buf, /* in: buffer to copy to */
const buf_frame_t* frame) /* in: buffer frame */
2005-10-27 07:29:40 +00:00
{
ut_ad(buf && frame);
ut_memcpy(buf, frame, UNIV_PAGE_SIZE);
return(buf);
}
/************************************************************************
Calculates a folded value of a file page address to use in the page hash
table. */
UNIV_INLINE
ulint
buf_page_address_fold(
/*==================*/
/* out: the folded value */
ulint space, /* in: space id */
ulint offset) /* in: offset of the page within space */
{
return((space << 20) + space + offset);
}
2005-10-27 07:29:40 +00:00
/************************************************************************
This function is used to get info if there is an io operation
going on on a buffer page. */
UNIV_INLINE
ibool
buf_page_io_query(
/*==============*/
/* out: TRUE if io going on */
buf_page_t* bpage) /* in: buf_pool block, must be bufferfixed */
2005-10-27 07:29:40 +00:00
{
ibool io_fixed;
buf_pool_mutex_enter();
2005-10-27 07:29:40 +00:00
ut_ad(buf_page_in_file(bpage));
ut_ad(bpage->buf_fix_count > 0);
2005-10-27 07:29:40 +00:00
io_fixed = buf_page_get_io_fix(bpage) != BUF_IO_NONE;
buf_pool_mutex_exit();
2005-10-27 07:29:40 +00:00
return(io_fixed);
2005-10-27 07:29:40 +00:00
}
/************************************************************************
Gets the youngest modification log sequence number for a frame.
Returns zero if not file page or no modification occurred yet. */
2005-10-27 07:29:40 +00:00
UNIV_INLINE
ib_uint64_t
buf_page_get_newest_modification(
/*=============================*/
/* out: newest modification to page */
const buf_page_t* bpage) /* in: block containing the
page frame */
2005-10-27 07:29:40 +00:00
{
ib_uint64_t lsn;
mutex_t* block_mutex = buf_page_get_mutex(bpage);
mutex_enter(block_mutex);
2005-10-27 07:29:40 +00:00
if (buf_page_in_file(bpage)) {
lsn = bpage->newest_modification;
2005-10-27 07:29:40 +00:00
} else {
lsn = 0;
2005-10-27 07:29:40 +00:00
}
mutex_exit(block_mutex);
2005-10-27 07:29:40 +00:00
return(lsn);
}
/************************************************************************
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
on the block. */
UNIV_INLINE
void
2005-10-27 07:29:40 +00:00
buf_block_modify_clock_inc(
/*=======================*/
buf_block_t* block) /* in: block */
{
#ifdef UNIV_SYNC_DEBUG
ut_ad((buf_pool_mutex_own()
&& (block->page.buf_fix_count == 0))
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
2005-10-27 07:29:40 +00:00
#endif /* UNIV_SYNC_DEBUG */
block->modify_clock++;
2005-10-27 07:29:40 +00:00
}
/************************************************************************
Returns the value of the modify clock. The caller must have an s-lock
2005-10-27 07:29:40 +00:00
or x-lock on the block. */
UNIV_INLINE
ib_uint64_t
2005-10-27 07:29:40 +00:00
buf_block_get_modify_clock(
/*=======================*/
/* out: value */
buf_block_t* block) /* in: block */
{
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_SHARED)
|| rw_lock_own(&(block->lock), RW_LOCK_EXCLUSIVE));
2005-10-27 07:29:40 +00:00
#endif /* UNIV_SYNC_DEBUG */
return(block->modify_clock);
}
/***********************************************************************
Increments the bufferfix count. */
UNIV_INLINE
void
buf_block_buf_fix_inc_func(
/*=======================*/
#ifdef UNIV_SYNC_DEBUG
const char* file, /* in: file name */
ulint line, /* in: line */
#endif /* UNIV_SYNC_DEBUG */
buf_block_t* block) /* in: block to bufferfix */
2005-10-27 07:29:40 +00:00
{
#ifdef UNIV_SYNC_DEBUG
2005-10-27 07:29:40 +00:00
ibool ret;
ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
ut_a(ret);
#endif /* UNIV_SYNC_DEBUG */
ut_ad(mutex_own(&block->mutex));
block->page.buf_fix_count++;
2005-10-27 07:29:40 +00:00
}
#ifdef UNIV_SYNC_DEBUG
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
2005-10-27 07:29:40 +00:00
#else /* UNIV_SYNC_DEBUG */
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
2005-10-27 07:29:40 +00:00
#endif /* UNIV_SYNC_DEBUG */
/***********************************************************************
Decrements the bufferfix count. */
UNIV_INLINE
void
buf_block_buf_fix_dec(
/*==================*/
buf_block_t* block) /* in: block to bufferunfix */
{
ut_ad(mutex_own(&block->mutex));
block->page.buf_fix_count--;
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&block->debug_latch);
#endif
}
2005-10-27 07:29:40 +00:00
/**********************************************************************
Returns the control block of a file page, NULL if not found. */
UNIV_INLINE
buf_page_t*
2005-10-27 07:29:40 +00:00
buf_page_hash_get(
/*==============*/
/* out: block, NULL if not found */
ulint space, /* in: space id */
ulint offset) /* in: offset of the page within space */
{
buf_page_t* bpage;
2005-10-27 07:29:40 +00:00
ulint fold;
2005-10-27 07:29:40 +00:00
ut_ad(buf_pool);
ut_ad(buf_pool_mutex_own());
2005-10-27 07:29:40 +00:00
/* Look for the page in the hash table */
fold = buf_page_address_fold(space, offset);
HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,
ut_ad(bpage->in_page_hash && !bpage->in_zip_hash
&& buf_page_in_file(bpage)),
bpage->space == space && bpage->offset == offset);
if (bpage) {
ut_a(buf_page_in_file(bpage));
ut_ad(bpage->in_page_hash);
ut_ad(!bpage->in_zip_hash);
UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
}
return(bpage);
2005-10-27 07:29:40 +00:00
}
/**********************************************************************
Returns the control block of a file page, NULL if not found
or an uncompressed page frame does not exist. */
UNIV_INLINE
buf_block_t*
buf_block_hash_get(
/*===============*/
/* out: block, NULL if not found */
ulint space, /* in: space id */
ulint offset) /* in: offset of the page within space */
{
return(buf_page_get_block(buf_page_hash_get(space, offset)));
}
/************************************************************************
Returns TRUE if the page can be found in the buffer pool hash table. NOTE
that it is possible that the page is not yet read from disk, though. */
UNIV_INLINE
ibool
buf_page_peek(
/*==========*/
/* out: TRUE if found from page hash table,
NOTE that the page is not necessarily yet read
from disk! */
ulint space, /* in: space id */
ulint offset) /* in: page number */
{
const buf_page_t* bpage;
buf_pool_mutex_enter();
bpage = buf_page_hash_get(space, offset);
buf_pool_mutex_exit();
return(bpage != NULL);
}
/************************************************************************
Releases a compressed-only page acquired with buf_page_get_zip(). */
UNIV_INLINE
void
buf_page_release_zip(
/*=================*/
buf_page_t* bpage) /* in: buffer block */
{
buf_block_t* block;
ut_ad(bpage);
ut_a(bpage->buf_fix_count > 0);
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
mutex_enter(&buf_pool_zip_mutex);
bpage->buf_fix_count--;
mutex_exit(&buf_pool_zip_mutex);
return;
case BUF_BLOCK_FILE_PAGE:
block = (buf_block_t*) bpage;
mutex_enter(&block->mutex);
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&block->debug_latch);
#endif
bpage->buf_fix_count--;
mutex_exit(&block->mutex);
return;
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:
break;
}
ut_error;
}
2005-10-27 07:29:40 +00:00
/************************************************************************
Decrements the bufferfix count of a buffer control block and releases
a latch, if specified. */
UNIV_INLINE
void
buf_page_release(
/*=============*/
buf_block_t* block, /* in: buffer block */
ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH,
RW_NO_LATCH */
mtr_t* mtr) /* in: mtr */
{
ut_ad(block);
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_a(block->page.buf_fix_count > 0);
2005-10-27 07:29:40 +00:00
if (rw_latch == RW_X_LATCH && mtr->modifications) {
buf_pool_mutex_enter();
2005-10-27 07:29:40 +00:00
buf_flush_note_modification(block, mtr);
buf_pool_mutex_exit();
2005-10-27 07:29:40 +00:00
}
mutex_enter(&block->mutex);
2005-10-27 07:29:40 +00:00
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
block->page.buf_fix_count--;
2005-10-27 07:29:40 +00:00
/* Dirty blocks should be in the flush list. */
ut_ad(!block->page.oldest_modification
|| block->page.in_flush_list);
mutex_exit(&block->mutex);
2005-10-27 07:29:40 +00:00
if (rw_latch == RW_S_LATCH) {
rw_lock_s_unlock(&(block->lock));
} else if (rw_latch == RW_X_LATCH) {
rw_lock_x_unlock(&(block->lock));
}
}
#ifdef UNIV_SYNC_DEBUG
/*************************************************************************
Adds latch level info for the rw-lock protecting the buffer frame. This
should be called in the debug version after a successful latching of a
page if we know the latching order level of the acquired latch. */
2005-10-27 07:29:40 +00:00
UNIV_INLINE
void
buf_block_dbg_add_level(
/*====================*/
buf_block_t* block, /* in: buffer page
where we have acquired latch */
ulint level) /* in: latching order level */
2005-10-27 07:29:40 +00:00
{
sync_thread_add_level(&block->lock, level);
2005-10-27 07:29:40 +00:00
}
#endif /* UNIV_SYNC_DEBUG */