mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
1547 lines
53 KiB
C
1547 lines
53 KiB
C
/*****************************************************************************
|
|
|
|
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/**************************************************//**
|
|
@file include/buf0buf.h
|
|
The database buffer pool high-level routines
|
|
|
|
Created 11/5/1995 Heikki Tuuri
|
|
*******************************************************/
|
|
|
|
#ifndef buf0buf_h
|
|
#define buf0buf_h
|
|
|
|
#include "univ.i"
|
|
#include "fil0fil.h"
|
|
#include "mtr0types.h"
|
|
#include "buf0types.h"
|
|
#include "hash0hash.h"
|
|
#include "ut0byte.h"
|
|
#include "page0types.h"
|
|
#ifndef UNIV_HOTBACKUP
|
|
#include "os0proc.h"
|
|
|
|
/** @name Modes for buf_page_get_gen */
|
|
/* @{ */
|
|
#define BUF_GET 10 /*!< get always */
|
|
#define BUF_GET_IF_IN_POOL 11 /*!< get if in pool */
|
|
#define BUF_GET_NO_LATCH 14 /*!< get and bufferfix, but
|
|
set no latch; we have
|
|
separated this case, because
|
|
it is error-prone programming
|
|
not to set a latch, and it
|
|
should be used with care */
|
|
/* @} */
|
|
/** @name Modes for buf_page_get_known_nowait */
|
|
/* @{ */
|
|
#define BUF_MAKE_YOUNG 51 /*!< Move the block to the
|
|
start of the LRU list if there
|
|
is a danger that the block
|
|
would drift out of the buffer
|
|
pool*/
|
|
#define BUF_KEEP_OLD 52 /*!< Preserve the current LRU
|
|
position of the block. */
|
|
/* @} */
|
|
|
|
extern buf_pool_t* buf_pool; /*!< The buffer pool of the database */
|
|
#ifdef UNIV_DEBUG
|
|
extern ibool buf_debug_prints;/*!< If this is set TRUE, the program
|
|
prints info whenever read or flush
|
|
occurs */
|
|
#endif /* UNIV_DEBUG */
|
|
extern ulint srv_buf_pool_write_requests; /*!< variable to count write request
|
|
issued */
|
|
#else /* !UNIV_HOTBACKUP */
|
|
extern buf_block_t* back_block1; /*!< first block, for --apply-log */
|
|
extern buf_block_t* back_block2; /*!< second block, for page reorganize */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
/** Magic value to use instead of checksums when they are disabled */
|
|
#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
|
|
|
|
/** @brief States of a control block
|
|
@see buf_page_struct
|
|
|
|
The enumeration values must be 0..7. */
|
|
enum buf_page_state {
|
|
BUF_BLOCK_ZIP_FREE = 0, /*!< contains a free
|
|
compressed page */
|
|
BUF_BLOCK_ZIP_PAGE, /*!< contains a clean
|
|
compressed page */
|
|
BUF_BLOCK_ZIP_DIRTY, /*!< contains a compressed
|
|
page that is in the
|
|
buf_pool->flush_list */
|
|
|
|
BUF_BLOCK_NOT_USED, /*!< is in the free list;
|
|
must be after the BUF_BLOCK_ZIP_
|
|
constants for compressed-only pages
|
|
@see buf_block_state_valid() */
|
|
BUF_BLOCK_READY_FOR_USE, /*!< when buf_LRU_get_free_block
|
|
returns a block, it is in this state */
|
|
BUF_BLOCK_FILE_PAGE, /*!< contains a buffered file page */
|
|
BUF_BLOCK_MEMORY, /*!< contains some main memory
|
|
object */
|
|
BUF_BLOCK_REMOVE_HASH /*!< hash index should be removed
|
|
before putting to the free list */
|
|
};
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/********************************************************************//**
|
|
Creates the buffer pool.
|
|
@return own: buf_pool object, NULL if not enough memory or error */
|
|
UNIV_INTERN
|
|
buf_pool_t*
|
|
buf_pool_init(void);
|
|
/*===============*/
|
|
/********************************************************************//**
|
|
Frees the buffer pool at shutdown. This must not be invoked before
|
|
freeing all mutexes. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_pool_free(void);
|
|
/*===============*/
|
|
|
|
/********************************************************************//**
|
|
Drops the adaptive hash index. To prevent a livelock, this function
|
|
is only to be called while holding btr_search_latch and while
|
|
btr_search_enabled == FALSE. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_pool_drop_hash_index(void);
|
|
/*==========================*/
|
|
|
|
/********************************************************************//**
|
|
Relocate a buffer control block. Relocates the block on the LRU list
|
|
and in buf_pool->page_hash. Does not relocate bpage->list.
|
|
The caller must take care of relocating bpage->list. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_relocate(
|
|
/*=========*/
|
|
buf_page_t* bpage, /*!< in/out: control block being relocated;
|
|
buf_page_get_state(bpage) must be
|
|
BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
|
|
buf_page_t* dpage) /*!< in/out: destination control block */
|
|
__attribute__((nonnull));
|
|
/********************************************************************//**
|
|
Resizes the buffer pool. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_pool_resize(void);
|
|
/*=================*/
|
|
/*********************************************************************//**
|
|
Gets the current size of buffer buf_pool in bytes.
|
|
@return size in bytes */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_pool_get_curr_size(void);
|
|
/*========================*/
|
|
/********************************************************************//**
|
|
Gets the smallest oldest_modification lsn for any page in the pool. Returns
|
|
zero if all modified pages have been flushed to disk.
|
|
@return oldest modification in pool, zero if none */
|
|
UNIV_INLINE
|
|
ib_uint64_t
|
|
buf_pool_get_oldest_modification(void);
|
|
/*==================================*/
|
|
/********************************************************************//**
|
|
Allocates a buffer block.
|
|
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
|
|
UNIV_INLINE
|
|
buf_block_t*
|
|
buf_block_alloc(
|
|
/*============*/
|
|
ulint zip_size); /*!< in: compressed page size in bytes,
|
|
or 0 if uncompressed tablespace */
|
|
/********************************************************************//**
|
|
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 */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
/*********************************************************************//**
|
|
Copies contents of a buffer frame to a given buffer.
|
|
@return buf */
|
|
UNIV_INLINE
|
|
byte*
|
|
buf_frame_copy(
|
|
/*===========*/
|
|
byte* buf, /*!< in: buffer to copy to */
|
|
const buf_frame_t* frame); /*!< in: buffer frame */
|
|
#ifndef UNIV_HOTBACKUP
|
|
/**************************************************************//**
|
|
NOTE! The following macros should be used instead of buf_page_get_gen,
|
|
to improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed
|
|
in LA! */
|
|
#define buf_page_get(SP, ZS, OF, LA, MTR) buf_page_get_gen(\
|
|
SP, ZS, OF, LA, NULL,\
|
|
BUF_GET, __FILE__, __LINE__, MTR)
|
|
/**************************************************************//**
|
|
Use these macros to bufferfix a page with no latching. Remember not to
|
|
read the contents of the page unless you know it is safe. Do not modify
|
|
the contents of the page! We have separated this case, because it is
|
|
error-prone programming not to set a latch, and it should be used
|
|
with care. */
|
|
#define buf_page_get_with_no_latch(SP, ZS, OF, MTR) buf_page_get_gen(\
|
|
SP, ZS, OF, RW_NO_LATCH, NULL,\
|
|
BUF_GET_NO_LATCH, __FILE__, __LINE__, MTR)
|
|
/**************************************************************//**
|
|
NOTE! The following macros should be used instead of
|
|
buf_page_optimistic_get_func, to improve debugging. Only values RW_S_LATCH and
|
|
RW_X_LATCH are allowed as LA! */
|
|
#define buf_page_optimistic_get(LA, BL, MC, MTR) \
|
|
buf_page_optimistic_get_func(LA, BL, MC, __FILE__, __LINE__, MTR)
|
|
/********************************************************************//**
|
|
This is the general function used to get optimistic access to a database
|
|
page.
|
|
@return TRUE if success */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_page_optimistic_get_func(
|
|
/*=========================*/
|
|
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
|
|
buf_block_t* block, /*!< in: guessed block */
|
|
ib_uint64_t modify_clock,/*!< in: modify clock value if mode is
|
|
..._GUESS_ON_CLOCK */
|
|
const char* file, /*!< in: file name */
|
|
ulint line, /*!< in: line where called */
|
|
mtr_t* mtr); /*!< in: mini-transaction */
|
|
/********************************************************************//**
|
|
This is used to get access to a known database page, when no waiting can be
|
|
done.
|
|
@return TRUE if success */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_page_get_known_nowait(
|
|
/*======================*/
|
|
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
|
|
buf_block_t* block, /*!< in: the known page */
|
|
ulint mode, /*!< in: BUF_MAKE_YOUNG or BUF_KEEP_OLD */
|
|
const char* file, /*!< in: file name */
|
|
ulint line, /*!< in: line where called */
|
|
mtr_t* mtr); /*!< in: mini-transaction */
|
|
|
|
/*******************************************************************//**
|
|
Given a tablespace id and page number tries to get that page. If the
|
|
page is not in the buffer pool it is not loaded and NULL is returned.
|
|
Suitable for using when holding the kernel mutex. */
|
|
UNIV_INTERN
|
|
const buf_block_t*
|
|
buf_page_try_get_func(
|
|
/*==================*/
|
|
ulint space_id,/*!< in: tablespace id */
|
|
ulint page_no,/*!< in: page number */
|
|
const char* file, /*!< in: file name */
|
|
ulint line, /*!< in: line where called */
|
|
mtr_t* mtr); /*!< in: mini-transaction */
|
|
|
|
/** Tries to get a page. If the page is not in the buffer pool it is
|
|
not loaded. Suitable for using when holding the kernel mutex.
|
|
@param space_id in: tablespace id
|
|
@param page_no in: page number
|
|
@param mtr in: mini-transaction
|
|
@return the page if in buffer pool, NULL if not */
|
|
#define buf_page_try_get(space_id, page_no, mtr) \
|
|
buf_page_try_get_func(space_id, page_no, __FILE__, __LINE__, mtr);
|
|
|
|
/********************************************************************//**
|
|
Get read access to a compressed page (usually of type
|
|
FIL_PAGE_TYPE_ZBLOB or FIL_PAGE_TYPE_ZBLOB2).
|
|
The page must be released with buf_page_release_zip().
|
|
NOTE: the page is not protected by any latch. Mutual exclusion has to
|
|
be implemented at a higher level. In other words, all possible
|
|
accesses to a given page through this function must be protected by
|
|
the same set of mutexes or latches.
|
|
@return pointer to the block, or NULL if not compressed */
|
|
UNIV_INTERN
|
|
buf_page_t*
|
|
buf_page_get_zip(
|
|
/*=============*/
|
|
ulint space, /*!< in: space id */
|
|
ulint zip_size,/*!< in: compressed page size */
|
|
ulint offset);/*!< in: page number */
|
|
/********************************************************************//**
|
|
This is the general function used to get access to a database page.
|
|
@return pointer to the block or NULL */
|
|
UNIV_INTERN
|
|
buf_block_t*
|
|
buf_page_get_gen(
|
|
/*=============*/
|
|
ulint space, /*!< in: space id */
|
|
ulint zip_size,/*!< in: compressed page size in bytes
|
|
or 0 for uncompressed pages */
|
|
ulint offset, /*!< in: page number */
|
|
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
|
|
buf_block_t* guess, /*!< in: guessed block or NULL */
|
|
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
|
|
BUF_GET_NO_LATCH */
|
|
const char* file, /*!< in: file name */
|
|
ulint line, /*!< in: line where called */
|
|
mtr_t* mtr); /*!< in: mini-transaction */
|
|
/********************************************************************//**
|
|
Initializes a page to the buffer buf_pool. The page is usually not read
|
|
from a file even if it cannot be found in the buffer buf_pool. This is one
|
|
of the functions which perform to a block a state transition NOT_USED =>
|
|
FILE_PAGE (the other is buf_page_get_gen).
|
|
@return pointer to the block, page bufferfixed */
|
|
UNIV_INTERN
|
|
buf_block_t*
|
|
buf_page_create(
|
|
/*============*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset, /*!< in: offset of the page within space in units of
|
|
a page */
|
|
ulint zip_size,/*!< in: compressed page size, or 0 */
|
|
mtr_t* mtr); /*!< in: mini-transaction handle */
|
|
#else /* !UNIV_HOTBACKUP */
|
|
/********************************************************************//**
|
|
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_page_init_for_backup_restore(
|
|
/*=============================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset, /*!< in: offset of the page within space
|
|
in units of a page */
|
|
ulint zip_size,/*!< in: compressed page size in bytes
|
|
or 0 for uncompressed pages */
|
|
buf_block_t* block); /*!< in: block to init */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/********************************************************************//**
|
|
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 */
|
|
/********************************************************************//**
|
|
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 */
|
|
/********************************************************************//**
|
|
Moves a page to the start of the buffer pool LRU list. This high-level
|
|
function can be used to prevent an important page from slipping out of
|
|
the buffer pool. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_page_make_young(
|
|
/*================*/
|
|
buf_page_t* bpage); /*!< in: buffer block of a file page */
|
|
/********************************************************************//**
|
|
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.
|
|
|
|
@return TRUE if found in the page hash table */
|
|
UNIV_INLINE
|
|
ibool
|
|
buf_page_peek(
|
|
/*==========*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset);/*!< in: page number */
|
|
/********************************************************************//**
|
|
Resets the check_index_page_at_flush field of a page if found in the buffer
|
|
pool. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_reset_check_index_page_at_flush(
|
|
/*================================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset);/*!< in: page number */
|
|
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
|
/********************************************************************//**
|
|
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
|
|
This function should be called when we free a file page and want the
|
|
debug version to check that it is not accessed any more unless
|
|
reallocated.
|
|
@return control block if found in page hash table, otherwise NULL */
|
|
UNIV_INTERN
|
|
buf_page_t*
|
|
buf_page_set_file_page_was_freed(
|
|
/*=============================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset);/*!< in: page number */
|
|
/********************************************************************//**
|
|
Sets file_page_was_freed FALSE if the page is found in the buffer pool.
|
|
This function should be called when we free a file page and want the
|
|
debug version to check that it is not accessed any more unless
|
|
reallocated.
|
|
@return control block if found in page hash table, otherwise NULL */
|
|
UNIV_INTERN
|
|
buf_page_t*
|
|
buf_page_reset_file_page_was_freed(
|
|
/*===============================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset); /*!< in: page number */
|
|
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
|
/********************************************************************//**
|
|
Reads the freed_page_clock of a buffer block.
|
|
@return freed_page_clock */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_page_get_freed_page_clock(
|
|
/*==========================*/
|
|
const buf_page_t* bpage) /*!< in: block */
|
|
__attribute__((pure));
|
|
/********************************************************************//**
|
|
Reads the freed_page_clock of a buffer block.
|
|
@return freed_page_clock */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_block_get_freed_page_clock(
|
|
/*===========================*/
|
|
const buf_block_t* block) /*!< in: block */
|
|
__attribute__((pure));
|
|
|
|
/********************************************************************//**
|
|
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.
|
|
@return TRUE if should be made younger */
|
|
UNIV_INLINE
|
|
ibool
|
|
buf_page_peek_if_too_old(
|
|
/*=====================*/
|
|
const buf_page_t* bpage); /*!< in: block to make younger */
|
|
/********************************************************************//**
|
|
Returns the current state of is_hashed of a page. FALSE if the page is
|
|
not in the pool. NOTE that this operation does not fix the page in the
|
|
pool if it is found there.
|
|
@return TRUE if page hash index is built in search system */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_page_peek_if_search_hashed(
|
|
/*===========================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset);/*!< in: page number */
|
|
/********************************************************************//**
|
|
Gets the youngest modification log sequence number for a frame.
|
|
Returns zero if not file page or no modification occurred yet.
|
|
@return newest modification to page */
|
|
UNIV_INLINE
|
|
ib_uint64_t
|
|
buf_page_get_newest_modification(
|
|
/*=============================*/
|
|
const buf_page_t* bpage); /*!< in: block containing the
|
|
page frame */
|
|
/********************************************************************//**
|
|
Increments the modify clock of a frame by 1. The caller must (1) own the
|
|
buf_pool mutex and block bufferfix count has to be zero, (2) or own an x-lock
|
|
on the block. */
|
|
UNIV_INLINE
|
|
void
|
|
buf_block_modify_clock_inc(
|
|
/*=======================*/
|
|
buf_block_t* block); /*!< in: block */
|
|
/********************************************************************//**
|
|
Returns the value of the modify clock. The caller must have an s-lock
|
|
or x-lock on the block.
|
|
@return value */
|
|
UNIV_INLINE
|
|
ib_uint64_t
|
|
buf_block_get_modify_clock(
|
|
/*=======================*/
|
|
buf_block_t* block); /*!< in: block */
|
|
#else /* !UNIV_HOTBACKUP */
|
|
# define buf_block_modify_clock_inc(block) ((void) 0)
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
/********************************************************************//**
|
|
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 32-bit and 64-bit architectures.
|
|
@return checksum */
|
|
UNIV_INTERN
|
|
ulint
|
|
buf_calc_page_new_checksum(
|
|
/*=======================*/
|
|
const byte* page); /*!< in: buffer page */
|
|
UNIV_INTERN
|
|
ulint
|
|
buf_calc_page_new_checksum_32(
|
|
/*==========================*/
|
|
const byte* page); /*!< in: buffer page */
|
|
/********************************************************************//**
|
|
In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
|
|
looked at the first few bytes of the page. This calculates that old
|
|
checksum.
|
|
NOTE: we must first store the new formula checksum to
|
|
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
|
|
because this takes that field as an input!
|
|
@return checksum */
|
|
UNIV_INTERN
|
|
ulint
|
|
buf_calc_page_old_checksum(
|
|
/*=======================*/
|
|
const byte* page); /*!< in: buffer page */
|
|
/********************************************************************//**
|
|
Checks if a page is corrupt.
|
|
@return TRUE if corrupted */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_page_is_corrupted(
|
|
/*==================*/
|
|
const byte* read_buf, /*!< in: a database page */
|
|
ulint zip_size); /*!< in: size of compressed page;
|
|
0 for uncompressed pages */
|
|
#ifndef UNIV_HOTBACKUP
|
|
/**********************************************************************//**
|
|
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 */
|
|
ulint* space, /*!< out: space id */
|
|
fil_addr_t* addr); /*!< out: page offset and byte offset */
|
|
/**********************************************************************//**
|
|
Gets the hash value of a block. This can be used in searches in the
|
|
lock hash table.
|
|
@return lock hash value */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_block_get_lock_hash_val(
|
|
/*========================*/
|
|
const buf_block_t* block) /*!< in: block */
|
|
__attribute__((pure));
|
|
#ifdef UNIV_DEBUG
|
|
/*********************************************************************//**
|
|
Finds a block in the buffer pool that points to a
|
|
given compressed page.
|
|
@return buffer block pointing to the compressed page, or NULL */
|
|
UNIV_INTERN
|
|
buf_block_t*
|
|
buf_pool_contains_zip(
|
|
/*==================*/
|
|
const void* data); /*!< in: pointer to compressed page */
|
|
#endif /* UNIV_DEBUG */
|
|
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
|
/*********************************************************************//**
|
|
Validates the buffer pool data structure.
|
|
@return TRUE */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_validate(void);
|
|
/*==============*/
|
|
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
|
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
|
/*********************************************************************//**
|
|
Prints info of the buffer pool data structure. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_print(void);
|
|
/*============*/
|
|
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
/********************************************************************//**
|
|
Prints a page to stderr. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_page_print(
|
|
/*===========*/
|
|
const byte* read_buf, /*!< in: a database page */
|
|
ulint zip_size); /*!< in: compressed page size, or
|
|
0 for uncompressed pages */
|
|
/********************************************************************//**
|
|
Decompress a block.
|
|
@return TRUE if successful */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_zip_decompress(
|
|
/*===============*/
|
|
buf_block_t* block, /*!< in/out: block */
|
|
ibool check); /*!< in: TRUE=verify the page checksum */
|
|
#ifndef UNIV_HOTBACKUP
|
|
#ifdef UNIV_DEBUG
|
|
/*********************************************************************//**
|
|
Returns the number of latched pages in the buffer pool.
|
|
@return number of latched pages */
|
|
UNIV_INTERN
|
|
ulint
|
|
buf_get_latched_pages_number(void);
|
|
/*==============================*/
|
|
#endif /* UNIV_DEBUG */
|
|
/*********************************************************************//**
|
|
Returns the number of pending buf pool ios.
|
|
@return number of pending I/O operations */
|
|
UNIV_INTERN
|
|
ulint
|
|
buf_get_n_pending_ios(void);
|
|
/*=======================*/
|
|
/*********************************************************************//**
|
|
Prints info of the buffer i/o. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_print_io(
|
|
/*=========*/
|
|
FILE* file); /*!< in: file where to print */
|
|
/*********************************************************************//**
|
|
Returns the ratio in percents of modified pages in the buffer pool /
|
|
database pages in the buffer pool.
|
|
@return modified page percentage ratio */
|
|
UNIV_INTERN
|
|
ulint
|
|
buf_get_modified_ratio_pct(void);
|
|
/*============================*/
|
|
/**********************************************************************//**
|
|
Refreshes the statistics used to print per-second averages. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_refresh_io_stats(void);
|
|
/*======================*/
|
|
/*********************************************************************//**
|
|
Asserts that all file pages in the buffer are in a replaceable state.
|
|
@return TRUE */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_all_freed(void);
|
|
/*===============*/
|
|
/*********************************************************************//**
|
|
Checks that there currently are no pending i/o-operations for the buffer
|
|
pool.
|
|
@return TRUE if there is no pending i/o */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_pool_check_no_pending_io(void);
|
|
/*==============================*/
|
|
/*********************************************************************//**
|
|
Invalidates the file pages in the buffer pool when an archive recovery is
|
|
completed. All the file pages buffered must be in a replaceable state when
|
|
this function is called: not latched and not modified. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_pool_invalidate(void);
|
|
/*=====================*/
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
/*========================================================================
|
|
--------------------------- LOWER LEVEL ROUTINES -------------------------
|
|
=========================================================================*/
|
|
|
|
#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. */
|
|
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 */
|
|
#else /* UNIV_SYNC_DEBUG */
|
|
# define buf_block_dbg_add_level(block, level) /* nothing */
|
|
#endif /* UNIV_SYNC_DEBUG */
|
|
/*********************************************************************//**
|
|
Gets the state of a block.
|
|
@return state */
|
|
UNIV_INLINE
|
|
enum buf_page_state
|
|
buf_page_get_state(
|
|
/*===============*/
|
|
const buf_page_t* bpage); /*!< in: pointer to the control block */
|
|
/*********************************************************************//**
|
|
Gets the state of a block.
|
|
@return state */
|
|
UNIV_INLINE
|
|
enum buf_page_state
|
|
buf_block_get_state(
|
|
/*================*/
|
|
const buf_block_t* block) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
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 */
|
|
/*********************************************************************//**
|
|
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 */
|
|
/*********************************************************************//**
|
|
Determines if a block is mapped to a tablespace.
|
|
@return TRUE if mapped */
|
|
UNIV_INLINE
|
|
ibool
|
|
buf_page_in_file(
|
|
/*=============*/
|
|
const buf_page_t* bpage) /*!< in: pointer to control block */
|
|
__attribute__((pure));
|
|
#ifndef UNIV_HOTBACKUP
|
|
/*********************************************************************//**
|
|
Determines if a block should be on unzip_LRU list.
|
|
@return TRUE if block belongs to unzip_LRU */
|
|
UNIV_INLINE
|
|
ibool
|
|
buf_page_belongs_to_unzip_LRU(
|
|
/*==========================*/
|
|
const buf_page_t* bpage) /*!< in: pointer to control block */
|
|
__attribute__((pure));
|
|
|
|
/*********************************************************************//**
|
|
Gets the mutex of a block.
|
|
@return pointer to mutex protecting bpage */
|
|
UNIV_INLINE
|
|
mutex_t*
|
|
buf_page_get_mutex(
|
|
/*===============*/
|
|
const buf_page_t* bpage) /*!< in: pointer to control block */
|
|
__attribute__((pure));
|
|
|
|
/*************************************************************************
|
|
Gets the mutex of a block and enter the mutex with consistency. */
|
|
UNIV_INLINE
|
|
mutex_t*
|
|
buf_page_get_mutex_enter(
|
|
/*=========================*/
|
|
const buf_page_t* bpage) /*!< in: pointer to control block */
|
|
__attribute__((pure));
|
|
|
|
/*********************************************************************//**
|
|
Get the flush type of a page.
|
|
@return flush type */
|
|
UNIV_INLINE
|
|
enum buf_flush
|
|
buf_page_get_flush_type(
|
|
/*====================*/
|
|
const buf_page_t* bpage) /*!< in: buffer page */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
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 */
|
|
/*********************************************************************//**
|
|
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 */
|
|
/*********************************************************************//**
|
|
Gets the io_fix state of a block.
|
|
@return io_fix state */
|
|
UNIV_INLINE
|
|
enum buf_io_fix
|
|
buf_page_get_io_fix(
|
|
/*================*/
|
|
const buf_page_t* bpage) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Gets the io_fix state of a block.
|
|
@return io_fix state */
|
|
UNIV_INLINE
|
|
enum buf_io_fix
|
|
buf_block_get_io_fix(
|
|
/*================*/
|
|
const buf_block_t* block) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
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 */
|
|
/*********************************************************************//**
|
|
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 */
|
|
|
|
/********************************************************************//**
|
|
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 */
|
|
__attribute__((pure));
|
|
|
|
/*********************************************************************//**
|
|
Determine if a block has been flagged old.
|
|
@return TRUE if old */
|
|
UNIV_INLINE
|
|
ibool
|
|
buf_page_is_old(
|
|
/*============*/
|
|
const buf_page_t* bpage) /*!< in: control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Flag a block old. */
|
|
UNIV_INLINE
|
|
void
|
|
buf_page_set_old(
|
|
/*=============*/
|
|
buf_page_t* bpage, /*!< in/out: control block */
|
|
ibool old); /*!< in: old */
|
|
/*********************************************************************//**
|
|
Determine the time of first access of a block in the buffer pool.
|
|
@return ut_time_ms() at the time of first access, 0 if not accessed */
|
|
UNIV_INLINE
|
|
unsigned
|
|
buf_page_is_accessed(
|
|
/*=================*/
|
|
const buf_page_t* bpage) /*!< in: control block */
|
|
__attribute__((nonnull, pure));
|
|
/*********************************************************************//**
|
|
Flag a block accessed. */
|
|
UNIV_INLINE
|
|
void
|
|
buf_page_set_accessed(
|
|
/*==================*/
|
|
buf_page_t* bpage, /*!< in/out: control block */
|
|
ulint time_ms) /*!< in: ut_time_ms() */
|
|
__attribute__((nonnull));
|
|
/*********************************************************************//**
|
|
Gets the buf_block_t handle of a buffered file block if an uncompressed
|
|
page frame exists, or NULL.
|
|
@return control block, or NULL */
|
|
UNIV_INLINE
|
|
buf_block_t*
|
|
buf_page_get_block(
|
|
/*===============*/
|
|
buf_page_t* bpage) /*!< in: control block, or NULL */
|
|
__attribute__((pure));
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
#ifdef UNIV_DEBUG
|
|
/*********************************************************************//**
|
|
Gets a pointer to the memory frame of a block.
|
|
@return pointer to the frame */
|
|
UNIV_INLINE
|
|
buf_frame_t*
|
|
buf_block_get_frame(
|
|
/*================*/
|
|
const buf_block_t* block) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
#else /* UNIV_DEBUG */
|
|
# define buf_block_get_frame(block) (block ? (block)->frame : 0)
|
|
#endif /* UNIV_DEBUG */
|
|
/*********************************************************************//**
|
|
Gets the space id of a block.
|
|
@return space id */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_page_get_space(
|
|
/*===============*/
|
|
const buf_page_t* bpage) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Gets the space id of a block.
|
|
@return space id */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_block_get_space(
|
|
/*================*/
|
|
const buf_block_t* block) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Gets the page number of a block.
|
|
@return page number */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_page_get_page_no(
|
|
/*=================*/
|
|
const buf_page_t* bpage) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Gets the page number of a block.
|
|
@return page number */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_block_get_page_no(
|
|
/*==================*/
|
|
const buf_block_t* block) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Gets the compressed page size of a block.
|
|
@return compressed page size, or 0 */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_page_get_zip_size(
|
|
/*==================*/
|
|
const buf_page_t* bpage) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Gets the compressed page size of a block.
|
|
@return compressed page size, or 0 */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_block_get_zip_size(
|
|
/*===================*/
|
|
const buf_block_t* block) /*!< in: pointer to the control block */
|
|
__attribute__((pure));
|
|
/*********************************************************************//**
|
|
Gets the compressed page descriptor corresponding to an uncompressed page
|
|
if applicable. */
|
|
#define buf_block_get_page_zip(block) \
|
|
(UNIV_LIKELY_NULL((block)->page.zip.data) ? &(block)->page.zip : NULL)
|
|
#ifndef UNIV_HOTBACKUP
|
|
/*******************************************************************//**
|
|
Gets the block to whose frame the pointer is pointing to.
|
|
@return pointer to block, never NULL */
|
|
UNIV_INTERN
|
|
buf_block_t*
|
|
buf_block_align(
|
|
/*============*/
|
|
const byte* ptr); /*!< in: pointer to a frame */
|
|
/********************************************************************//**
|
|
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
|
|
the buf_block_t itself or a member of it
|
|
@return TRUE if ptr belongs to a buf_block_t struct */
|
|
UNIV_INTERN
|
|
ibool
|
|
buf_pointer_is_block_field(
|
|
/*=======================*/
|
|
const void* ptr); /*!< in: pointer not
|
|
dereferenced */
|
|
/** Find out if a pointer corresponds to a buf_block_t::mutex.
|
|
@param m in: mutex candidate
|
|
@return TRUE if m is a buf_block_t::mutex */
|
|
#define buf_pool_is_block_mutex(m) \
|
|
buf_pointer_is_block_field((const void*)(m))
|
|
/** Find out if a pointer corresponds to a buf_block_t::lock.
|
|
@param l in: rw-lock candidate
|
|
@return TRUE if l is a buf_block_t::lock */
|
|
#define buf_pool_is_block_lock(l) \
|
|
buf_pointer_is_block_field((const void*)(l))
|
|
|
|
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
|
|
/*********************************************************************//**
|
|
Gets the compressed page descriptor corresponding to an uncompressed page
|
|
if applicable.
|
|
@return compressed page descriptor, or NULL */
|
|
UNIV_INLINE
|
|
const page_zip_des_t*
|
|
buf_frame_get_page_zip(
|
|
/*===================*/
|
|
const byte* ptr); /*!< in: pointer to the page */
|
|
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
|
|
/********************************************************************//**
|
|
Function which inits a page for read to the buffer buf_pool. If the page is
|
|
(1) already in buf_pool, or
|
|
(2) if we specify to read only ibuf pages and the page is not an ibuf page, or
|
|
(3) if the space is deleted or being deleted,
|
|
then this function does nothing.
|
|
Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock
|
|
on the buffer frame. The io-handler must take care that the flag is cleared
|
|
and the lock released later.
|
|
@return pointer to the block or NULL */
|
|
UNIV_INTERN
|
|
buf_page_t*
|
|
buf_page_init_for_read(
|
|
/*===================*/
|
|
ulint* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED */
|
|
ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ... */
|
|
ulint space, /*!< in: space id */
|
|
ulint zip_size,/*!< in: compressed page size, or 0 */
|
|
ibool unzip, /*!< in: TRUE=request uncompressed page */
|
|
ib_int64_t tablespace_version,/*!< in: prevents reading from a wrong
|
|
version of the tablespace in case we have done
|
|
DISCARD + IMPORT */
|
|
ulint offset);/*!< in: page number */
|
|
/********************************************************************//**
|
|
Completes an asynchronous read or write request of a file page to or from
|
|
the buffer pool. */
|
|
UNIV_INTERN
|
|
void
|
|
buf_page_io_complete(
|
|
/*=================*/
|
|
buf_page_t* bpage, /*!< in: pointer to the block in question */
|
|
trx_t* trx);
|
|
/********************************************************************//**
|
|
Calculates a folded value of a file page address to use in the page hash
|
|
table.
|
|
@return the folded value */
|
|
UNIV_INLINE
|
|
ulint
|
|
buf_page_address_fold(
|
|
/*==================*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset) /*!< in: offset of the page within space */
|
|
__attribute__((const));
|
|
/******************************************************************//**
|
|
Returns the control block of a file page, NULL if not found.
|
|
@return block, NULL if not found */
|
|
UNIV_INLINE
|
|
buf_page_t*
|
|
buf_page_hash_get(
|
|
/*==============*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset);/*!< in: offset of the page within space */
|
|
/******************************************************************//**
|
|
Returns the control block of a file page, NULL if not found
|
|
or an uncompressed page frame does not exist.
|
|
@return block, NULL if not found */
|
|
UNIV_INLINE
|
|
buf_block_t*
|
|
buf_block_hash_get(
|
|
/*===============*/
|
|
ulint space, /*!< in: space id */
|
|
ulint offset);/*!< in: offset of the page within space */
|
|
/*********************************************************************//**
|
|
Gets the current length of the free list of buffer blocks.
|
|
@return length of the free list */
|
|
UNIV_INTERN
|
|
ulint
|
|
buf_get_free_list_len(void);
|
|
/*=======================*/
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
|
|
|
|
/** The common buffer control block structure
|
|
for compressed and uncompressed frames */
|
|
|
|
struct buf_page_struct{
|
|
/** @name General fields
|
|
None of these bit-fields must be modified without holding
|
|
buf_page_get_mutex() [buf_block_struct::mutex or
|
|
buf_pool_zip_mutex], since they can be stored in the same
|
|
machine word. Some of these fields are additionally protected
|
|
by buf_pool_mutex. */
|
|
/* @{ */
|
|
|
|
unsigned space:32; /*!< tablespace id; also protected
|
|
by buf_pool_mutex. */
|
|
unsigned offset:32; /*!< page number; also protected
|
|
by buf_pool_mutex. */
|
|
|
|
unsigned state:3; /*!< state of the control block; also
|
|
protected by buf_pool_mutex.
|
|
State transitions from
|
|
BUF_BLOCK_READY_FOR_USE to
|
|
BUF_BLOCK_MEMORY need not be
|
|
protected by buf_page_get_mutex().
|
|
@see enum buf_page_state */
|
|
#ifndef UNIV_HOTBACKUP
|
|
unsigned flush_type:2; /*!< if this block is currently being
|
|
flushed to disk, this tells the
|
|
flush_type.
|
|
@see enum buf_flush */
|
|
unsigned io_fix:2; /*!< type of pending I/O operation;
|
|
also protected by buf_pool_mutex
|
|
@see enum buf_io_fix */
|
|
unsigned buf_fix_count:25;/*!< count of how manyfold this block
|
|
is currently bufferfixed */
|
|
/* @} */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
page_zip_des_t zip; /*!< compressed page; zip.data
|
|
(but not the data it points to) is
|
|
also protected by buf_pool_mutex */
|
|
#ifndef UNIV_HOTBACKUP
|
|
buf_page_t* hash; /*!< node used in chaining to
|
|
buf_pool->page_hash or
|
|
buf_pool->zip_hash */
|
|
#ifdef UNIV_DEBUG
|
|
ibool in_page_hash; /*!< TRUE if in buf_pool->page_hash */
|
|
ibool in_zip_hash; /*!< TRUE if in buf_pool->zip_hash */
|
|
#endif /* UNIV_DEBUG */
|
|
|
|
/** @name Page flushing fields
|
|
All these are protected by buf_pool_mutex. */
|
|
/* @{ */
|
|
|
|
/* UT_LIST_NODE_T(buf_page_t) list; */
|
|
/*!< based on state, this is a
|
|
list node, protected only by
|
|
buf_pool_mutex, in one of the
|
|
following lists in buf_pool:
|
|
|
|
- BUF_BLOCK_NOT_USED: free
|
|
- BUF_BLOCK_FILE_PAGE: flush_list
|
|
- BUF_BLOCK_ZIP_DIRTY: flush_list
|
|
- BUF_BLOCK_ZIP_PAGE: zip_clean
|
|
- BUF_BLOCK_ZIP_FREE: zip_free[]
|
|
|
|
The contents of the list node
|
|
is undefined if !in_flush_list
|
|
&& state == BUF_BLOCK_FILE_PAGE,
|
|
or if state is one of
|
|
BUF_BLOCK_MEMORY,
|
|
BUF_BLOCK_REMOVE_HASH or
|
|
BUF_BLOCK_READY_IN_USE. */
|
|
|
|
/* resplit for optimistic use */
|
|
UT_LIST_NODE_T(buf_page_t) free;
|
|
UT_LIST_NODE_T(buf_page_t) flush_list;
|
|
UT_LIST_NODE_T(buf_page_t) zip_list; /* zip_clean or zip_free[] */
|
|
#ifdef UNIV_DEBUG
|
|
ibool in_flush_list; /*!< TRUE if in buf_pool->flush_list;
|
|
when buf_pool_mutex is free, the
|
|
following should hold: in_flush_list
|
|
== (state == BUF_BLOCK_FILE_PAGE
|
|
|| state == BUF_BLOCK_ZIP_DIRTY) */
|
|
ibool in_free_list; /*!< TRUE if in buf_pool->free; when
|
|
buf_pool_mutex is free, the following
|
|
should hold: in_free_list
|
|
== (state == BUF_BLOCK_NOT_USED) */
|
|
#endif /* UNIV_DEBUG */
|
|
ib_uint64_t newest_modification;
|
|
/*!< log sequence number of
|
|
the youngest modification to
|
|
this block, zero if not
|
|
modified */
|
|
ib_uint64_t oldest_modification;
|
|
/*!< log sequence number of
|
|
the START of the log entry
|
|
written of the oldest
|
|
modification to this block
|
|
which has not yet been flushed
|
|
on disk; zero if all
|
|
modifications are on disk */
|
|
/* @} */
|
|
/** @name LRU replacement algorithm fields
|
|
These fields are protected by buf_pool_mutex only (not
|
|
buf_pool_zip_mutex or buf_block_struct::mutex). */
|
|
/* @{ */
|
|
|
|
UT_LIST_NODE_T(buf_page_t) LRU;
|
|
/*!< node of the LRU list */
|
|
//#ifdef UNIV_DEBUG
|
|
ibool in_LRU_list; /*!< TRUE if the page is in
|
|
the LRU list; used in
|
|
debugging */
|
|
//#endif /* UNIV_DEBUG */
|
|
unsigned old:1; /*!< TRUE if the block is in the old
|
|
blocks in buf_pool->LRU_old */
|
|
unsigned freed_page_clock:31;/*!< the value of
|
|
buf_pool->freed_page_clock
|
|
when this block was the last
|
|
time put to the head of the
|
|
LRU list; a thread is allowed
|
|
to read this for heuristic
|
|
purposes without holding any
|
|
mutex or latch */
|
|
unsigned access_time:32; /*!< time of first access, or
|
|
0 if the block was never accessed
|
|
in the buffer pool */
|
|
/* @} */
|
|
ibool is_corrupt;
|
|
# ifdef UNIV_DEBUG_FILE_ACCESSES
|
|
ibool file_page_was_freed;
|
|
/*!< this is set to TRUE when fsp
|
|
frees a page in buffer pool */
|
|
# endif /* UNIV_DEBUG_FILE_ACCESSES */
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
};
|
|
|
|
/** The buffer control block structure */
|
|
|
|
struct buf_block_struct{
|
|
|
|
/** @name General fields */
|
|
/* @{ */
|
|
|
|
buf_page_t page; /*!< page information; this must
|
|
be the first field, so that
|
|
buf_pool->page_hash can point
|
|
to buf_page_t or buf_block_t */
|
|
byte* frame; /*!< pointer to buffer frame which
|
|
is of size UNIV_PAGE_SIZE, and
|
|
aligned to an address divisible by
|
|
UNIV_PAGE_SIZE */
|
|
#ifndef UNIV_HOTBACKUP
|
|
UT_LIST_NODE_T(buf_block_t) unzip_LRU;
|
|
/*!< node of the decompressed LRU list;
|
|
a block is in the unzip_LRU list
|
|
if page.state == BUF_BLOCK_FILE_PAGE
|
|
and page.zip.data != NULL */
|
|
//#ifdef UNIV_DEBUG
|
|
ibool in_unzip_LRU_list;/*!< TRUE if the page is in the
|
|
decompressed LRU list;
|
|
used in debugging */
|
|
//#endif /* UNIV_DEBUG */
|
|
mutex_t mutex; /*!< mutex protecting this block:
|
|
state (also protected by the buffer
|
|
pool mutex), io_fix, buf_fix_count,
|
|
and accessed; we introduce this new
|
|
mutex in InnoDB-5.1 to relieve
|
|
contention on the buffer pool mutex */
|
|
rw_lock_t lock; /*!< read-write lock of the buffer
|
|
frame */
|
|
unsigned lock_hash_val:32;/*!< hashed value of the page address
|
|
in the record lock hash table */
|
|
unsigned check_index_page_at_flush:1;
|
|
/*!< TRUE if we know that this is
|
|
an index page, and want the database
|
|
to check its consistency before flush;
|
|
note that there may be pages in the
|
|
buffer pool which are index pages,
|
|
but this flag is not set because
|
|
we do not keep track of all pages */
|
|
/* @} */
|
|
/** @name Optimistic search field */
|
|
/* @{ */
|
|
|
|
ib_uint64_t modify_clock; /*!< this clock is incremented every
|
|
time a pointer to a record on the
|
|
page may become obsolete; this is
|
|
used in the optimistic cursor
|
|
positioning: if the modify clock has
|
|
not changed, we know that the pointer
|
|
is still valid; this field may be
|
|
changed if the thread (1) owns the
|
|
pool mutex and the page is not
|
|
bufferfixed, or (2) the thread has an
|
|
x-latch on the block */
|
|
/* @} */
|
|
/** @name Hash search fields (unprotected)
|
|
NOTE that these fields are NOT protected by any semaphore! */
|
|
/* @{ */
|
|
|
|
ulint n_hash_helps; /*!< counter which controls building
|
|
of a new hash index for the page */
|
|
ulint n_fields; /*!< recommended prefix length for hash
|
|
search: number of full fields */
|
|
ulint n_bytes; /*!< recommended prefix: number of bytes
|
|
in an incomplete field */
|
|
ibool left_side; /*!< TRUE or FALSE, depending on
|
|
whether the leftmost record of several
|
|
records with the same prefix should be
|
|
indexed in the hash index */
|
|
/* @} */
|
|
|
|
/** @name Hash search fields
|
|
These 6 fields may only be modified when we have
|
|
an x-latch on btr_search_latch AND
|
|
- we are holding an s-latch or x-latch on buf_block_struct::lock or
|
|
- we know that buf_block_struct::buf_fix_count == 0.
|
|
|
|
An exception to this is when we init or create a page
|
|
in the buffer pool in buf0buf.c. */
|
|
|
|
/* @{ */
|
|
|
|
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
|
ulint n_pointers; /*!< used in debugging: the number of
|
|
pointers in the adaptive hash index
|
|
pointing to this frame */
|
|
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
|
unsigned is_hashed:1; /*!< TRUE if hash index has
|
|
already been built on this
|
|
page; note that it does not
|
|
guarantee that the index is
|
|
complete, though: there may
|
|
have been hash collisions,
|
|
record deletions, etc. */
|
|
unsigned curr_n_fields:10;/*!< prefix length for hash indexing:
|
|
number of full fields */
|
|
unsigned curr_n_bytes:15;/*!< number of bytes in hash
|
|
indexing */
|
|
unsigned curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
|
|
dict_index_t* index; /*!< Index for which the adaptive
|
|
hash index has been created. */
|
|
/* @} */
|
|
# ifdef UNIV_SYNC_DEBUG
|
|
/** @name Debug fields */
|
|
/* @{ */
|
|
rw_lock_t debug_latch; /*!< in the debug version, each thread
|
|
which bufferfixes the block acquires
|
|
an s-latch here; so we can use the
|
|
debug utilities in sync0rw */
|
|
/* @} */
|
|
# endif
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
};
|
|
|
|
/** Check if a buf_block_t object is in a valid state
|
|
@param block buffer block
|
|
@return TRUE if valid */
|
|
#define buf_block_state_valid(block) \
|
|
(buf_block_get_state(block) >= BUF_BLOCK_NOT_USED \
|
|
&& (buf_block_get_state(block) <= BUF_BLOCK_REMOVE_HASH))
|
|
|
|
#ifndef UNIV_HOTBACKUP
|
|
/**********************************************************************//**
|
|
Compute the hash fold value for blocks in buf_pool->zip_hash. */
|
|
/* @{ */
|
|
#define BUF_POOL_ZIP_FOLD_PTR(ptr) ((ulint) (ptr) / UNIV_PAGE_SIZE)
|
|
#define BUF_POOL_ZIP_FOLD(b) BUF_POOL_ZIP_FOLD_PTR((b)->frame)
|
|
#define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
|
|
/* @} */
|
|
|
|
/** @brief The buffer pool statistics structure. */
|
|
struct buf_pool_stat_struct{
|
|
ulint n_page_gets; /*!< number of page gets performed;
|
|
also successful searches through
|
|
the adaptive hash index are
|
|
counted as page gets; this field
|
|
is NOT protected by the buffer
|
|
pool mutex */
|
|
ulint n_pages_read; /*!< number read operations */
|
|
ulint n_pages_written;/*!< number write operations */
|
|
ulint n_pages_created;/*!< number of pages created
|
|
in the pool with no read */
|
|
ulint n_ra_pages_read;/*!< number of pages read in
|
|
as part of read ahead */
|
|
ulint n_ra_pages_evicted;/*!< number of read ahead
|
|
pages that are evicted without
|
|
being accessed */
|
|
ulint n_pages_made_young; /*!< number of pages made young, in
|
|
calls to buf_LRU_make_block_young() */
|
|
ulint n_pages_not_made_young; /*!< number of pages not made
|
|
young because the first access
|
|
was not long enough ago, in
|
|
buf_page_peek_if_too_old() */
|
|
};
|
|
|
|
/** @brief The buffer pool structure.
|
|
|
|
NOTE! The definition appears here only for other modules of this
|
|
directory (buf) to see it. Do not use from outside! */
|
|
|
|
struct buf_pool_struct{
|
|
|
|
/** @name General fields */
|
|
/* @{ */
|
|
|
|
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 buf_page_t or
|
|
buf_block_t file pages,
|
|
buf_page_in_file() == TRUE,
|
|
indexed by (space_id, offset) */
|
|
hash_table_t* zip_hash; /*!< hash table of buf_block_t blocks
|
|
whose frames are allocated to the
|
|
zip buddy system,
|
|
indexed by block->frame */
|
|
ulint n_pend_reads; /*!< number of pending read operations */
|
|
ulint n_pend_unzip; /*!< number of pending decompressions */
|
|
|
|
time_t last_printout_time;
|
|
/*!< when buf_print_io was last time
|
|
called */
|
|
buf_pool_stat_t stat; /*!< current statistics */
|
|
buf_pool_stat_t old_stat; /*!< old statistics */
|
|
|
|
/* @} */
|
|
|
|
/** @name Page flushing algorithm fields */
|
|
|
|
/* @{ */
|
|
|
|
UT_LIST_BASE_NODE_T(buf_page_t) flush_list;
|
|
/*!< base node of the modified block
|
|
list */
|
|
ibool init_flush[BUF_FLUSH_N_TYPES];
|
|
/*!< this is TRUE when a flush of the
|
|
given type is being initialized */
|
|
ulint n_flush[BUF_FLUSH_N_TYPES];
|
|
/*!< this is the number of pending
|
|
writes in the given flush type */
|
|
os_event_t no_flush[BUF_FLUSH_N_TYPES];
|
|
/*!< this is in the set state
|
|
when there is no flush batch
|
|
of the given type running */
|
|
ulint freed_page_clock;/*!< a sequence number used
|
|
to count the number of buffer
|
|
blocks removed from the end of
|
|
the LRU list; NOTE that this
|
|
counter may wrap around at 4
|
|
billion! A thread is allowed
|
|
to read this for heuristic
|
|
purposes without holding any
|
|
mutex or latch */
|
|
ulint LRU_flush_ended;/*!< when an LRU flush ends for a page,
|
|
this is incremented by one; this is
|
|
set to zero when a buffer block is
|
|
allocated */
|
|
|
|
/* @} */
|
|
/** @name LRU replacement algorithm fields */
|
|
/* @{ */
|
|
|
|
UT_LIST_BASE_NODE_T(buf_page_t) free;
|
|
/*!< base node of the free
|
|
block list */
|
|
UT_LIST_BASE_NODE_T(buf_page_t) LRU;
|
|
/*!< base node of the LRU list */
|
|
buf_page_t* LRU_old; /*!< pointer to the about
|
|
buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
|
|
oldest blocks in the LRU list;
|
|
NULL if LRU length less than
|
|
BUF_LRU_OLD_MIN_LEN;
|
|
NOTE: when LRU_old != NULL, its length
|
|
should always equal LRU_old_len */
|
|
ulint LRU_old_len; /*!< length of the LRU list from
|
|
the block to which LRU_old points
|
|
onward, including that block;
|
|
see buf0lru.c for the restrictions
|
|
on this value; 0 if LRU_old == NULL;
|
|
NOTE: LRU_old_len must be adjusted
|
|
whenever LRU_old shrinks or grows! */
|
|
|
|
UT_LIST_BASE_NODE_T(buf_block_t) unzip_LRU;
|
|
/*!< base node of the
|
|
unzip_LRU list */
|
|
|
|
/* @} */
|
|
/** @name Buddy allocator fields
|
|
The buddy allocator is used for allocating compressed page
|
|
frames and buf_page_t descriptors of blocks that exist
|
|
in the buffer pool only in compressed form. */
|
|
/* @{ */
|
|
UT_LIST_BASE_NODE_T(buf_page_t) zip_clean;
|
|
/*!< unmodified compressed pages */
|
|
UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES_MAX];
|
|
/*!< buddy free lists */
|
|
//#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
|
|
//# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
|
|
//#endif
|
|
#if BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE
|
|
# error "BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE"
|
|
#endif
|
|
/* @} */
|
|
};
|
|
|
|
/** mutex protecting the buffer pool struct and control blocks, except the
|
|
read-write lock in them */
|
|
extern mutex_t buf_pool_mutex;
|
|
extern mutex_t LRU_list_mutex;
|
|
extern mutex_t flush_list_mutex;
|
|
extern rw_lock_t page_hash_latch;
|
|
extern mutex_t free_list_mutex;
|
|
extern mutex_t zip_free_mutex;
|
|
extern mutex_t zip_hash_mutex;
|
|
/** mutex protecting the control blocks of compressed-only pages
|
|
(of type buf_page_t, not buf_block_t) */
|
|
extern mutex_t buf_pool_zip_mutex;
|
|
|
|
/** @name Accessors for buf_pool_mutex.
|
|
Use these instead of accessing buf_pool_mutex directly. */
|
|
/* @{ */
|
|
|
|
/** Test if buf_pool_mutex is owned. */
|
|
#define buf_pool_mutex_own() mutex_own(&buf_pool_mutex)
|
|
/** Acquire the buffer pool mutex. */
|
|
#define buf_pool_mutex_enter() do { \
|
|
ut_ad(!mutex_own(&buf_pool_zip_mutex)); \
|
|
mutex_enter(&buf_pool_mutex); \
|
|
} while (0)
|
|
|
|
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
|
|
/** Flag to forbid the release of the buffer pool mutex.
|
|
Protected by buf_pool_mutex. */
|
|
extern ulint buf_pool_mutex_exit_forbidden;
|
|
/** Forbid the release of the buffer pool mutex. */
|
|
# define buf_pool_mutex_exit_forbid() do { \
|
|
ut_ad(buf_pool_mutex_own()); \
|
|
buf_pool_mutex_exit_forbidden++; \
|
|
} while (0)
|
|
/** Allow the release of the buffer pool mutex. */
|
|
# define buf_pool_mutex_exit_allow() do { \
|
|
ut_ad(buf_pool_mutex_own()); \
|
|
ut_a(buf_pool_mutex_exit_forbidden); \
|
|
buf_pool_mutex_exit_forbidden--; \
|
|
} while (0)
|
|
/** Release the buffer pool mutex. */
|
|
# define buf_pool_mutex_exit() do { \
|
|
ut_a(!buf_pool_mutex_exit_forbidden); \
|
|
mutex_exit(&buf_pool_mutex); \
|
|
} while (0)
|
|
#else
|
|
/** Forbid the release of the buffer pool mutex. */
|
|
# define buf_pool_mutex_exit_forbid() ((void) 0)
|
|
/** Allow the release of the buffer pool mutex. */
|
|
# define buf_pool_mutex_exit_allow() ((void) 0)
|
|
/** Release the buffer pool mutex. */
|
|
# define buf_pool_mutex_exit() mutex_exit(&buf_pool_mutex)
|
|
#endif
|
|
#endif /* !UNIV_HOTBACKUP */
|
|
/* @} */
|
|
|
|
/**********************************************************************
|
|
Let us list the consistency conditions for different control block states.
|
|
|
|
NOT_USED: is in free list, not in LRU list, not in flush list, nor
|
|
page hash table
|
|
READY_FOR_USE: is not in free list, LRU list, or flush list, nor page
|
|
hash table
|
|
MEMORY: is not in free list, LRU list, or flush list, nor page
|
|
hash table
|
|
FILE_PAGE: space and offset are defined, is in page hash table
|
|
if io_fix == BUF_IO_WRITE,
|
|
pool: no_flush[flush_type] is in reset state,
|
|
pool: n_flush[flush_type] > 0
|
|
|
|
(1) if buf_fix_count == 0, then
|
|
is in LRU list, not in free list
|
|
is in flush list,
|
|
if and only if oldest_modification > 0
|
|
is x-locked,
|
|
if and only if io_fix == BUF_IO_READ
|
|
is s-locked,
|
|
if and only if io_fix == BUF_IO_WRITE
|
|
|
|
(2) if buf_fix_count > 0, then
|
|
is not in LRU list, not in free list
|
|
is in flush list,
|
|
if and only if oldest_modification > 0
|
|
if io_fix == BUF_IO_READ,
|
|
is x-locked
|
|
if io_fix == BUF_IO_WRITE,
|
|
is s-locked
|
|
|
|
State transitions:
|
|
|
|
NOT_USED => READY_FOR_USE
|
|
READY_FOR_USE => MEMORY
|
|
READY_FOR_USE => FILE_PAGE
|
|
MEMORY => NOT_USED
|
|
FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if
|
|
(1) buf_fix_count == 0,
|
|
(2) oldest_modification == 0, and
|
|
(3) io_fix == 0.
|
|
*/
|
|
|
|
#ifndef UNIV_NONINL
|
|
#include "buf0buf.ic"
|
|
#endif
|
|
|
|
#endif
|