1/*****************************************************************************
2
3Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/**************************************************//**
21@file include/buf0lru.h
22The database buffer pool LRU replacement algorithm
23
24Created 11/5/1995 Heikki Tuuri
25*******************************************************/
26
27#ifndef buf0lru_h
28#define buf0lru_h
29
30#include "univ.i"
31#include "ut0byte.h"
32#include "buf0types.h"
33
34// Forward declaration
35struct trx_t;
36struct fil_space_t;
37
38/******************************************************************//**
39Returns TRUE if less than 25 % of the buffer pool is available. This can be
40used in heuristics to prevent huge transactions eating up the whole buffer
41pool for their locks.
42@return TRUE if less than 25 % of buffer pool left */
43ibool
44buf_LRU_buf_pool_running_out(void);
45/*==============================*/
46
47/*#######################################################################
48These are low-level functions
49#########################################################################*/
50
51/** Minimum LRU list length for which the LRU_old pointer is defined */
52#define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */
53
54/** Empty the flush list for all pages belonging to a tablespace.
55@param[in] id tablespace identifier
56@param[in,out] observer flush observer,
57 or NULL if nothing is to be written */
58void
59buf_LRU_flush_or_remove_pages(
60 ulint id,
61 FlushObserver* observer
62#ifdef BTR_CUR_HASH_ADAPT
63 , bool drop_ahi = false /*!< whether to drop the adaptive hash index */
64#endif /* BTR_CUR_HASH_ADAPT */
65 );
66
67#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
68/********************************************************************//**
69Insert a compressed block into buf_pool->zip_clean in the LRU order. */
70void
71buf_LRU_insert_zip_clean(
72/*=====================*/
73 buf_page_t* bpage); /*!< in: pointer to the block in question */
74#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
75
76/******************************************************************//**
77Try to free a block. If bpage is a descriptor of a compressed-only
78page, the descriptor object will be freed as well.
79
80NOTE: If this function returns true, it will temporarily
81release buf_pool->mutex. Furthermore, the page frame will no longer be
82accessible via bpage.
83
84The caller must hold buf_pool->mutex and must not hold any
85buf_page_get_mutex() when calling this function.
86@return true if freed, false otherwise. */
87bool
88buf_LRU_free_page(
89/*==============*/
90 buf_page_t* bpage, /*!< in: block to be freed */
91 bool zip) /*!< in: true if should remove also the
92 compressed page of an uncompressed page */
93 MY_ATTRIBUTE((nonnull));
94/******************************************************************//**
95Try to free a replaceable block.
96@return true if found and freed */
97bool
98buf_LRU_scan_and_free_block(
99/*========================*/
100 buf_pool_t* buf_pool, /*!< in: buffer pool instance */
101 bool scan_all) /*!< in: scan whole LRU list
102 if true, otherwise scan only
103 'old' blocks. */
104 MY_ATTRIBUTE((nonnull,warn_unused_result));
105/******************************************************************//**
106Returns a free block from the buf_pool. The block is taken off the
107free list. If it is empty, returns NULL.
108@return a free control block, or NULL if the buf_block->free list is empty */
109buf_block_t*
110buf_LRU_get_free_only(
111/*==================*/
112 buf_pool_t* buf_pool); /*!< buffer pool instance */
113/******************************************************************//**
114Returns a free block from the buf_pool. The block is taken off the
115free list. If free list is empty, blocks are moved from the end of the
116LRU list to the free list.
117This function is called from a user thread when it needs a clean
118block to read in a page. Note that we only ever get a block from
119the free list. Even when we flush a page or find a page in LRU scan
120we put it to free list to be used.
121* iteration 0:
122 * get a block from free list, success:done
123 * if buf_pool->try_LRU_scan is set
124 * scan LRU up to srv_LRU_scan_depth to find a clean block
125 * the above will put the block on free list
126 * success:retry the free list
127 * flush one dirty page from tail of LRU to disk
128 * the above will put the block on free list
129 * success: retry the free list
130* iteration 1:
131 * same as iteration 0 except:
132 * scan whole LRU list
133 * scan LRU list even if buf_pool->try_LRU_scan is not set
134* iteration > 1:
135 * same as iteration 1 but sleep 10ms
136@return the free control block, in state BUF_BLOCK_READY_FOR_USE */
137buf_block_t*
138buf_LRU_get_free_block(
139/*===================*/
140 buf_pool_t* buf_pool) /*!< in/out: buffer pool instance */
141 MY_ATTRIBUTE((nonnull,warn_unused_result));
142/******************************************************************//**
143Determines if the unzip_LRU list should be used for evicting a victim
144instead of the general LRU list.
145@return TRUE if should use unzip_LRU */
146ibool
147buf_LRU_evict_from_unzip_LRU(
148/*=========================*/
149 buf_pool_t* buf_pool);
150/******************************************************************//**
151Puts a block back to the free list. */
152void
153buf_LRU_block_free_non_file_page(
154/*=============================*/
155 buf_block_t* block); /*!< in: block, must not contain a file page */
156/******************************************************************//**
157Adds a block to the LRU list. Please make sure that the page_size is
158already set when invoking the function, so that we can get correct
159page_size from the buffer page when adding a block into LRU */
160void
161buf_LRU_add_block(
162/*==============*/
163 buf_page_t* bpage, /*!< in: control block */
164 ibool old); /*!< in: TRUE if should be put to the old
165 blocks in the LRU list, else put to the
166 start; if the LRU list is very short, added to
167 the start regardless of this parameter */
168/******************************************************************//**
169Adds a block to the LRU list of decompressed zip pages. */
170void
171buf_unzip_LRU_add_block(
172/*====================*/
173 buf_block_t* block, /*!< in: control block */
174 ibool old); /*!< in: TRUE if should be put to the end
175 of the list, else put to the start */
176/******************************************************************//**
177Moves a block to the start of the LRU list. */
178void
179buf_LRU_make_block_young(
180/*=====================*/
181 buf_page_t* bpage); /*!< in: control block */
182/**********************************************************************//**
183Updates buf_pool->LRU_old_ratio.
184@return updated old_pct */
185uint
186buf_LRU_old_ratio_update(
187/*=====================*/
188 uint old_pct,/*!< in: Reserve this percentage of
189 the buffer pool for "old" blocks. */
190 ibool adjust);/*!< in: TRUE=adjust the LRU list;
191 FALSE=just assign buf_pool->LRU_old_ratio
192 during the initialization of InnoDB */
193/********************************************************************//**
194Update the historical stats that we are collecting for LRU eviction
195policy at the end of each interval. */
196void
197buf_LRU_stat_update(void);
198/*=====================*/
199
200/******************************************************************//**
201Remove one page from LRU list and put it to free list */
202void
203buf_LRU_free_one_page(
204/*==================*/
205 buf_page_t* bpage) /*!< in/out: block, must contain a file page and
206 be in a state where it can be freed; there
207 may or may not be a hash index to the page */
208 MY_ATTRIBUTE((nonnull));
209
210/******************************************************************//**
211Adjust LRU hazard pointers if needed. */
212void
213buf_LRU_adjust_hp(
214/*==============*/
215 buf_pool_t* buf_pool,/*!< in: buffer pool instance */
216 const buf_page_t* bpage); /*!< in: control block */
217
218#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
219/**********************************************************************//**
220Validates the LRU list.
221@return TRUE */
222ibool
223buf_LRU_validate(void);
224/*==================*/
225#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
226#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
227/**********************************************************************//**
228Prints the LRU list. */
229void
230buf_LRU_print(void);
231/*===============*/
232#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
233
234/** @name Heuristics for detecting index scan @{ */
235/** The denominator of buf_pool->LRU_old_ratio. */
236#define BUF_LRU_OLD_RATIO_DIV 1024
237/** Maximum value of buf_pool->LRU_old_ratio.
238@see buf_LRU_old_adjust_len
239@see buf_pool->LRU_old_ratio_update */
240#define BUF_LRU_OLD_RATIO_MAX BUF_LRU_OLD_RATIO_DIV
241/** Minimum value of buf_pool->LRU_old_ratio.
242@see buf_LRU_old_adjust_len
243@see buf_pool->LRU_old_ratio_update
244The minimum must exceed
245(BUF_LRU_OLD_TOLERANCE + 5) * BUF_LRU_OLD_RATIO_DIV / BUF_LRU_OLD_MIN_LEN. */
246#define BUF_LRU_OLD_RATIO_MIN 51
247
248#if BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX
249# error "BUF_LRU_OLD_RATIO_MIN >= BUF_LRU_OLD_RATIO_MAX"
250#endif
251#if BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV
252# error "BUF_LRU_OLD_RATIO_MAX > BUF_LRU_OLD_RATIO_DIV"
253#endif
254
255/** Move blocks to "new" LRU list only if the first access was at
256least this many milliseconds ago. Not protected by any mutex or latch. */
257extern uint buf_LRU_old_threshold_ms;
258/* @} */
259
260/** @brief Statistics for selecting the LRU list for eviction.
261
262These statistics are not 'of' LRU but 'for' LRU. We keep count of I/O
263and page_zip_decompress() operations. Based on the statistics we decide
264if we want to evict from buf_pool->unzip_LRU or buf_pool->LRU. */
265struct buf_LRU_stat_t
266{
267 ulint io; /**< Counter of buffer pool I/O operations. */
268 ulint unzip; /**< Counter of page_zip_decompress operations. */
269};
270
271/** Current operation counters. Not protected by any mutex.
272Cleared by buf_LRU_stat_update(). */
273extern buf_LRU_stat_t buf_LRU_stat_cur;
274
275/** Running sum of past values of buf_LRU_stat_cur.
276Updated by buf_LRU_stat_update(). Protected by buf_pool->mutex. */
277extern buf_LRU_stat_t buf_LRU_stat_sum;
278
279/********************************************************************//**
280Increments the I/O counter in buf_LRU_stat_cur. */
281#define buf_LRU_stat_inc_io() buf_LRU_stat_cur.io++
282/********************************************************************//**
283Increments the page_zip_decompress() counter in buf_LRU_stat_cur. */
284#define buf_LRU_stat_inc_unzip() buf_LRU_stat_cur.unzip++
285
286#endif
287