buf0buf.h 68.2 KB
Newer Older
1
/*****************************************************************************
2

3
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
4

5 6 7 8 9 10 11 12 13
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
14 15
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 17

*****************************************************************************/
18

19 20
/**************************************************//**
@file include/buf0buf.h
osku's avatar
osku committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34
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"
35 36
#include "page0types.h"
#ifndef UNIV_HOTBACKUP
inaam's avatar
inaam committed
37
#include "ut0rbt.h"
osku's avatar
osku committed
38 39
#include "os0proc.h"

40 41 42 43
/** @name Modes for buf_page_get_gen */
/* @{ */
#define BUF_GET			10	/*!< get always */
#define	BUF_GET_IF_IN_POOL	11	/*!< get if in pool */
44 45
#define BUF_PEEK_IF_IN_POOL	12	/*!< get if in pool, do not make
					the block young in the LRU list */
46 47 48 49 50 51
#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 */
52
#define BUF_GET_IF_IN_POOL_OR_WATCH	15
53
					/*!< Get the page only if it's in the
54 55
					buffer pool, if not then set a watch
					on the page. */
56 57 58
#define BUF_GET_POSSIBLY_FREED		16
					/*!< Like BUF_GET, but do not mind
					if the file page has been freed. */
59 60 61 62 63 64 65 66 67 68 69 70
/* @} */
/** @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. */
/* @} */

71 72 73 74
#define MAX_BUFFER_POOLS_BITS	6 	/*!< Number of bits to representing
					a buffer pool ID */
#define MAX_BUFFER_POOLS	(1 << MAX_BUFFER_POOLS_BITS)
					/*!< The maximum number of buffer
irana's avatar
irana committed
75 76 77 78 79
					pools that can be defined */

#define BUF_POOL_WATCH_SIZE 1		/*!< Maximum number of concurrent
					buffer pool watches */

80
extern	buf_pool_t*	buf_pool_ptr;	/*!< The buffer pools
irana's avatar
irana committed
81
					of the database */
osku's avatar
osku committed
82
#ifdef UNIV_DEBUG
83
extern ibool		buf_debug_prints;/*!< If this is set TRUE, the program
osku's avatar
osku committed
84 85 86
					prints info whenever read or flush
					occurs */
#endif /* UNIV_DEBUG */
87
extern ulint srv_buf_pool_write_requests; /*!< variable to count write request
88
					  issued */
irana's avatar
irana committed
89 90
extern ulint srv_buf_pool_instances;
extern ulint srv_buf_pool_curr_size;
91
#else /* !UNIV_HOTBACKUP */
92 93
extern buf_block_t*	back_block1;	/*!< first block, for --apply-log */
extern buf_block_t*	back_block2;	/*!< second block, for page reorganize */
94 95
#endif /* !UNIV_HOTBACKUP */

96
/** Magic value to use instead of checksums when they are disabled */
97
#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
osku's avatar
osku committed
98

99 100 101
/** @brief States of a control block
@see buf_page_struct

102
The enumeration values must be 0..7. */
103
enum buf_page_state {
104 105
	BUF_BLOCK_ZIP_FREE = 0,		/*!< contains a free
					compressed page */
106
	BUF_BLOCK_POOL_WATCH = 0,	/*!< a sentinel for the buffer pool
107
					watch, element of buf_pool->watch[] */
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	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
124 125 126
					before putting to the free list */
};

127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

/** This structure defines information we will fetch from each buffer pool. It
will be used to print table IO stats */
struct buf_pool_info_struct{
	/* General buffer pool info */
	ulint	pool_unique_id;		/*!< Buffer Pool ID */
	ulint	pool_size;		/*!< Buffer Pool size in pages */
	ulint	lru_len;		/*!< Length of buf_pool->LRU */
	ulint	old_lru_len;		/*!< buf_pool->LRU_old_len */
	ulint	free_list_len;		/*!< Length of buf_pool->free list */
	ulint	flush_list_len;		/*!< Length of buf_pool->flush_list */
	ulint	n_pend_unzip;		/*!< buf_pool->n_pend_unzip, pages
					pending decompress */
	ulint	n_pend_reads;		/*!< buf_pool->n_pend_reads, pages
					pending read */
	ulint	n_pending_flush_lru;	/*!< Pages pending flush in LRU */
	ulint	n_pending_flush_list;	/*!< Pages pending flush in FLUSH
					LIST */
	ulint	n_pending_flush_single_page;/*!< Pages pending flush in
					BUF_FLUSH_SINGLE_PAGE list */
	ulint	n_pages_made_young;	/*!< number of pages made young */
	ulint	n_pages_not_made_young;	/*!< number of pages not made young */
	ulint	n_pages_read;		/*!< buf_pool->n_pages_read */
	ulint	n_pages_created;	/*!< buf_pool->n_pages_created */
	ulint	n_pages_written;	/*!< buf_pool->n_pages_written */
	ulint	n_page_gets;		/*!< buf_pool->n_page_gets */
153 154
	ulint	n_ra_pages_read_rnd;	/*!< buf_pool->n_ra_pages_read_rnd,
					number of pages readahead */
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
	ulint	n_ra_pages_read;	/*!< buf_pool->n_ra_pages_read, number
					of pages readahead */
	ulint	n_ra_pages_evicted;	/*!< buf_pool->n_ra_pages_evicted,
					number of readahead pages evicted
					without access */
	ulint	n_page_get_delta;	/*!< num of buffer pool page gets since
					last printout */

	/* Buffer pool access stats */
	double	page_made_young_rate;	/*!< page made young rate in pages
					per second */
	double	page_not_made_young_rate;/*!< page not made young rate
					in pages per second */
	double	pages_read_rate;	/*!< num of pages read per second */
	double	pages_created_rate;	/*!< num of pages create per second */
	double	pages_written_rate;	/*!< num of  pages written per second */
	ulint	page_read_delta;	/*!< num of pages read since last
					printout */
	ulint	young_making_delta;	/*!< num of pages made young since
					last printout */
	ulint	not_young_making_delta;	/*!< num of pages not make young since
					last printout */

	/* Statistics about read ahead algorithm.  */
179 180
	double	pages_readahead_rnd_rate;/*!< random readahead rate in pages per
					second */
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
	double	pages_readahead_rate;	/*!< readahead rate in pages per
					second */
	double	pages_evicted_rate;	/*!< rate of readahead page evicted
					without access, in pages per second */

	/* Stats about LRU eviction */
	ulint	unzip_lru_len;		/*!< length of buf_pool->unzip_LRU
					list */
	/* Counters for LRU policy */
	ulint	io_sum;			/*!< buf_LRU_stat_sum.io */
	ulint	io_cur;			/*!< buf_LRU_stat_cur.io, num of IO
					for current interval */
	ulint	unzip_sum;		/*!< buf_LRU_stat_sum.unzip */
	ulint	unzip_cur;		/*!< buf_LRU_stat_cur.unzip, num
					pages decompressed in current
					interval */
};

typedef struct buf_pool_info_struct	buf_pool_info_t;

201
#ifndef UNIV_HOTBACKUP
irana's avatar
irana committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215
/********************************************************************//**
Acquire mutex on all buffer pool instances */
UNIV_INLINE
void
buf_pool_mutex_enter_all(void);
/*===========================*/

/********************************************************************//**
Release mutex on all buffer pool instances */
UNIV_INLINE
void
buf_pool_mutex_exit_all(void);
/*==========================*/

216
/********************************************************************//**
217 218
Creates the buffer pool.
@return	own: buf_pool object, NULL if not enough memory or error */
219
UNIV_INTERN
irana's avatar
irana committed
220 221 222 223 224
ulint
buf_pool_init(
/*=========*/
	ulint	size,		/*!< in: Size of the total pool in bytes */
	ulint	n_instances);	/*!< in: Number of instances */
225
/********************************************************************//**
226 227
Frees the buffer pool at shutdown.  This must not be invoked before
freeing all mutexes. */
228
UNIV_INTERN
229
void
irana's avatar
irana committed
230 231 232
buf_pool_free(
/*==========*/
	ulint	n_instances);	/*!< in: numbere of instances to free */
233

234
/********************************************************************//**
235
Clears the adaptive hash index on all pages in the buffer pool. */
236 237
UNIV_INTERN
void
238 239
buf_pool_clear_hash_index(void);
/*===========================*/
240

241
/********************************************************************//**
242
Relocate a buffer control block.  Relocates the block on the LRU list
243 244
and in buf_pool->page_hash.  Does not relocate bpage->list.
The caller must take care of relocating bpage->list. */
245
UNIV_INTERN
246 247 248
void
buf_relocate(
/*=========*/
249
	buf_page_t*	bpage,	/*!< in/out: control block being relocated;
250 251
				buf_page_get_state(bpage) must be
				BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
252
	buf_page_t*	dpage)	/*!< in/out: destination control block */
253
	__attribute__((nonnull));
254
/*********************************************************************//**
255 256
Gets the current size of buffer buf_pool in bytes.
@return	size in bytes */
osku's avatar
osku committed
257 258 259 260
UNIV_INLINE
ulint
buf_pool_get_curr_size(void);
/*========================*/
irana's avatar
irana committed
261 262 263 264 265 266 267
/*********************************************************************//**
Gets the current size of buffer buf_pool in frames.
@return	size in pages */
UNIV_INLINE
ulint
buf_pool_get_n_pages(void);
/*=======================*/
268
/********************************************************************//**
osku's avatar
osku committed
269
Gets the smallest oldest_modification lsn for any page in the pool. Returns
270 271
zero if all modified pages have been flushed to disk.
@return	oldest modification in pool, zero if none */
irana's avatar
irana committed
272
UNIV_INTERN
273
ib_uint64_t
osku's avatar
osku committed
274 275
buf_pool_get_oldest_modification(void);
/*==================================*/
276
/********************************************************************//**
Inaam Rana's avatar
Inaam Rana committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
Allocates a buf_page_t descriptor. This function must succeed. In case
of failure we assert in this function. */
UNIV_INLINE
buf_page_t*
buf_page_alloc_descriptor(void)
/*===========================*/
	__attribute__((malloc));
/********************************************************************//**
Free a buf_page_t descriptor. */
UNIV_INLINE
void
buf_page_free_descriptor(
/*=====================*/
	buf_page_t*	bpage)	/*!< in: bpage descriptor to free. */
	__attribute__((nonnull));
292

Inaam Rana's avatar
Inaam Rana committed
293
/********************************************************************//**
294 295
Allocates a buffer block.
@return	own: the allocated block, in state BUF_BLOCK_MEMORY */
irana's avatar
irana committed
296
UNIV_INTERN
297 298 299
buf_block_t*
buf_block_alloc(
/*============*/
300 301 302
	buf_pool_t*	buf_pool);	/*!< in: buffer pool instance,
					or NULL for round-robin selection
					of the buffer pool */
303
/********************************************************************//**
304 305 306 307 308
Frees a buffer block which does not contain a file page. */
UNIV_INLINE
void
buf_block_free(
/*===========*/
309
	buf_block_t*	block);	/*!< in, own: block to be freed */
310
#endif /* !UNIV_HOTBACKUP */
311
/*********************************************************************//**
312 313
Copies contents of a buffer frame to a given buffer.
@return	buf */
osku's avatar
osku committed
314 315 316 317
UNIV_INLINE
byte*
buf_frame_copy(
/*===========*/
318 319
	byte*			buf,	/*!< in: buffer to copy to */
	const buf_frame_t*	frame);	/*!< in: buffer frame */
320
#ifndef UNIV_HOTBACKUP
321
/**************************************************************//**
osku's avatar
osku committed
322 323 324
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! */
325 326
#define buf_page_get(SP, ZS, OF, LA, MTR)	 buf_page_get_gen(\
				SP, ZS, OF, LA, NULL,\
osku's avatar
osku committed
327
				BUF_GET, __FILE__, __LINE__, MTR)
328
/**************************************************************//**
osku's avatar
osku committed
329 330 331 332 333
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. */
334
#define buf_page_get_with_no_latch(SP, ZS, OF, MTR)	   buf_page_get_gen(\
335
				SP, ZS, OF, RW_NO_LATCH, NULL,\
336
				BUF_GET_NO_LATCH, __FILE__, __LINE__, MTR)
337
/********************************************************************//**
osku's avatar
osku committed
338
This is the general function used to get optimistic access to a database
339 340
page.
@return	TRUE if success */
341
UNIV_INTERN
osku's avatar
osku committed
342
ibool
343 344
buf_page_optimistic_get(
/*====================*/
345 346 347
	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
osku's avatar
osku committed
348
				..._GUESS_ON_CLOCK */
349 350 351
	const char*	file,	/*!< in: file name */
	ulint		line,	/*!< in: line where called */
	mtr_t*		mtr);	/*!< in: mini-transaction */
352
/********************************************************************//**
osku's avatar
osku committed
353
This is used to get access to a known database page, when no waiting can be
354 355
done.
@return	TRUE if success */
356
UNIV_INTERN
osku's avatar
osku committed
357 358 359
ibool
buf_page_get_known_nowait(
/*======================*/
360 361 362 363 364 365
	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 */
vasil's avatar
vasil committed
366

367
/*******************************************************************//**
vasil's avatar
vasil committed
368 369 370
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. */
371
UNIV_INTERN
372
const buf_block_t*
vasil's avatar
vasil committed
373 374
buf_page_try_get_func(
/*==================*/
375 376 377 378 379
	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 */
vasil's avatar
vasil committed
380

381 382 383 384 385 386
/** 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 */
vasil's avatar
vasil committed
387 388 389
#define buf_page_try_get(space_id, page_no, mtr)	\
	buf_page_try_get_func(space_id, page_no, __FILE__, __LINE__, mtr);

390
/********************************************************************//**
391 392
Get read access to a compressed page (usually of type
FIL_PAGE_TYPE_ZBLOB or FIL_PAGE_TYPE_ZBLOB2).
393 394 395 396
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
397 398
the same set of mutexes or latches.
@return	pointer to the block, or NULL if not compressed */
399
UNIV_INTERN
400 401 402
buf_page_t*
buf_page_get_zip(
/*=============*/
403 404 405
	ulint		space,	/*!< in: space id */
	ulint		zip_size,/*!< in: compressed page size */
	ulint		offset);/*!< in: page number */
406
/********************************************************************//**
407 408
This is the general function used to get access to a database page.
@return	pointer to the block or NULL */
409
UNIV_INTERN
410
buf_block_t*
osku's avatar
osku committed
411 412
buf_page_get_gen(
/*=============*/
413 414
	ulint		space,	/*!< in: space id */
	ulint		zip_size,/*!< in: compressed page size in bytes
415
				or 0 for uncompressed pages */
416 417 418 419
	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,
420
				BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH or
421
				BUF_GET_IF_IN_POOL_OR_WATCH */
422 423 424
	const char*	file,	/*!< in: file name */
	ulint		line,	/*!< in: line where called */
	mtr_t*		mtr);	/*!< in: mini-transaction */
425
/********************************************************************//**
osku's avatar
osku committed
426 427 428
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 =>
429 430
FILE_PAGE (the other is buf_page_get_gen).
@return	pointer to the block, page bufferfixed */
431
UNIV_INTERN
432
buf_block_t*
osku's avatar
osku committed
433 434
buf_page_create(
/*============*/
435 436
	ulint	space,	/*!< in: space id */
	ulint	offset,	/*!< in: offset of the page within space in units of
osku's avatar
osku committed
437
			a page */
438 439
	ulint	zip_size,/*!< in: compressed page size, or 0 */
	mtr_t*	mtr);	/*!< in: mini-transaction handle */
440
#else /* !UNIV_HOTBACKUP */
441
/********************************************************************//**
osku's avatar
osku committed
442
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
443
UNIV_INTERN
osku's avatar
osku committed
444 445 446
void
buf_page_init_for_backup_restore(
/*=============================*/
447 448
	ulint		space,	/*!< in: space id */
	ulint		offset,	/*!< in: offset of the page within space
osku's avatar
osku committed
449
				in units of a page */
450
	ulint		zip_size,/*!< in: compressed page size in bytes
451
				or 0 for uncompressed pages */
452
	buf_block_t*	block);	/*!< in: block to init */
453 454 455
#endif /* !UNIV_HOTBACKUP */

#ifndef UNIV_HOTBACKUP
456
/********************************************************************//**
457 458 459 460 461
Releases a compressed-only page acquired with buf_page_get_zip(). */
UNIV_INLINE
void
buf_page_release_zip(
/*=================*/
462
	buf_page_t*	bpage);		/*!< in: buffer block */
463
/********************************************************************//**
osku's avatar
osku committed
464 465 466 467 468 469
Decrements the bufferfix count of a buffer control block and releases
a latch, if specified. */
UNIV_INLINE
void
buf_page_release(
/*=============*/
470
	buf_block_t*	block,		/*!< in: buffer block */
inaam's avatar
inaam committed
471
	ulint		rw_latch);	/*!< in: RW_S_LATCH, RW_X_LATCH,
osku's avatar
osku committed
472
					RW_NO_LATCH */
473
/********************************************************************//**
osku's avatar
osku committed
474
Moves a page to the start of the buffer pool LRU list. This high-level
475
function can be used to prevent an important page from slipping out of
osku's avatar
osku committed
476
the buffer pool. */
477
UNIV_INTERN
osku's avatar
osku committed
478 479
void
buf_page_make_young(
480
/*================*/
481
	buf_page_t*	bpage);	/*!< in: buffer block of a file page */
482 483 484 485 486 487 488
/********************************************************************//**
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 */
489
UNIV_INLINE
osku's avatar
osku committed
490 491 492
ibool
buf_page_peek(
/*==========*/
493 494
	ulint	space,	/*!< in: space id */
	ulint	offset);/*!< in: page number */
495 496 497 498 499 500 501 502 503
/********************************************************************//**
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 */
504
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
505
/********************************************************************//**
osku's avatar
osku committed
506 507 508
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
509 510
reallocated.
@return	control block if found in page hash table, otherwise NULL */
511
UNIV_INTERN
512
buf_page_t*
osku's avatar
osku committed
513 514
buf_page_set_file_page_was_freed(
/*=============================*/
515 516
	ulint	space,	/*!< in: space id */
	ulint	offset);/*!< in: page number */
517
/********************************************************************//**
osku's avatar
osku committed
518 519 520
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
521 522
reallocated.
@return	control block if found in page hash table, otherwise NULL */
523
UNIV_INTERN
524
buf_page_t*
osku's avatar
osku committed
525 526
buf_page_reset_file_page_was_freed(
/*===============================*/
527 528
	ulint	space,	/*!< in: space id */
	ulint	offset);	/*!< in: page number */
529
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
530
/********************************************************************//**
531 532
Reads the freed_page_clock of a buffer block.
@return	freed_page_clock */
533 534 535 536
UNIV_INLINE
ulint
buf_page_get_freed_page_clock(
/*==========================*/
537
	const buf_page_t*	bpage)	/*!< in: block */
538
	__attribute__((pure));
539
/********************************************************************//**
540 541
Reads the freed_page_clock of a buffer block.
@return	freed_page_clock */
542 543 544 545
UNIV_INLINE
ulint
buf_block_get_freed_page_clock(
/*===========================*/
546
	const buf_block_t*	block)	/*!< in: block */
547 548
	__attribute__((pure));

549
/********************************************************************//**
550 551 552 553 554 555 556 557 558 559 560 561
Tells if a block is still close enough to the MRU end of the LRU list
meaning that it is not in danger of getting evicted and also implying
that it has been accessed recently.
Note that this is for heuristics only and does not reserve buffer pool
mutex.
@return	TRUE if block is close to MRU end of LRU */
UNIV_INLINE
ibool
buf_page_peek_if_young(
/*===================*/
	const buf_page_t*	bpage);	/*!< in: block */
/********************************************************************//**
osku's avatar
osku committed
562 563
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
564 565
mutex.
@return	TRUE if should be made younger */
osku's avatar
osku committed
566 567
UNIV_INLINE
ibool
568 569
buf_page_peek_if_too_old(
/*=====================*/
570
	const buf_page_t*	bpage);	/*!< in: block to make younger */
571
/********************************************************************//**
osku's avatar
osku committed
572
Gets the youngest modification log sequence number for a frame.
573 574
Returns zero if not file page or no modification occurred yet.
@return	newest modification to page */
osku's avatar
osku committed
575
UNIV_INLINE
576
ib_uint64_t
577 578
buf_page_get_newest_modification(
/*=============================*/
579
	const buf_page_t*	bpage);	/*!< in: block containing the
580
					page frame */
581
/********************************************************************//**
osku's avatar
osku committed
582
Increments the modify clock of a frame by 1. The caller must (1) own the
irana's avatar
irana committed
583
buf_pool->mutex and block bufferfix count has to be zero, (2) or own an x-lock
osku's avatar
osku committed
584 585
on the block. */
UNIV_INLINE
586
void
osku's avatar
osku committed
587 588
buf_block_modify_clock_inc(
/*=======================*/
589
	buf_block_t*	block);	/*!< in: block */
590
/********************************************************************//**
591
Returns the value of the modify clock. The caller must have an s-lock
592 593
or x-lock on the block.
@return	value */
osku's avatar
osku committed
594
UNIV_INLINE
595
ib_uint64_t
osku's avatar
osku committed
596 597
buf_block_get_modify_clock(
/*=======================*/
598
	buf_block_t*	block);	/*!< in: block */
599 600 601 602 603 604
/*******************************************************************//**
Increments the bufferfix count. */
UNIV_INLINE
void
buf_block_buf_fix_inc_func(
/*=======================*/
605
# ifdef UNIV_SYNC_DEBUG
606 607
	const char*	file,	/*!< in: file name */
	ulint		line,	/*!< in: line */
608
# endif /* UNIV_SYNC_DEBUG */
609 610
	buf_block_t*	block)	/*!< in/out: block to bufferfix */
	__attribute__((nonnull));
611
# ifdef UNIV_SYNC_DEBUG
612 613 614 615 616
/** Increments the bufferfix count.
@param b	in/out: block to bufferfix
@param f	in: file name where requested
@param l	in: line number where requested */
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
617
# else /* UNIV_SYNC_DEBUG */
618 619 620 621 622
/** Increments the bufferfix count.
@param b	in/out: block to bufferfix
@param f	in: file name where requested
@param l	in: line number where requested */
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
623 624 625 626
# endif /* UNIV_SYNC_DEBUG */
#else /* !UNIV_HOTBACKUP */
# define buf_block_modify_clock_inc(block) ((void) 0)
#endif /* !UNIV_HOTBACKUP */
627
/********************************************************************//**
osku's avatar
osku committed
628 629
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
630 631
on 32-bit and 64-bit architectures.
@return	checksum */
632
UNIV_INTERN
osku's avatar
osku committed
633 634 635
ulint
buf_calc_page_new_checksum(
/*=======================*/
636
	const byte*	page);	/*!< in: buffer page */
637
/********************************************************************//**
osku's avatar
osku committed
638 639
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
640
checksum.
osku's avatar
osku committed
641 642
NOTE: we must first store the new formula checksum to
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
643 644
because this takes that field as an input!
@return	checksum */
645
UNIV_INTERN
osku's avatar
osku committed
646 647 648
ulint
buf_calc_page_old_checksum(
/*=======================*/
649
	const byte*	 page);	/*!< in: buffer page */
650
/********************************************************************//**
651 652
Checks if a page is corrupt.
@return	TRUE if corrupted */
653
UNIV_INTERN
osku's avatar
osku committed
654 655 656
ibool
buf_page_is_corrupted(
/*==================*/
657 658
	const byte*	read_buf,	/*!< in: a database page */
	ulint		zip_size);	/*!< in: size of compressed page;
marko's avatar
marko committed
659
					0 for uncompressed pages */
660
#ifndef UNIV_HOTBACKUP
661
/**********************************************************************//**
osku's avatar
osku committed
662 663 664 665 666 667
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(
/*=================*/
668 669 670
	const void*	ptr,	/*!< in: pointer to a buffer frame */
	ulint*		space,	/*!< out: space id */
	fil_addr_t*	addr);	/*!< out: page offset and byte offset */
671
/**********************************************************************//**
672
Gets the hash value of a block. This can be used in searches in the
673 674
lock hash table.
@return	lock hash value */
osku's avatar
osku committed
675 676
UNIV_INLINE
ulint
677
buf_block_get_lock_hash_val(
osku's avatar
osku committed
678
/*========================*/
679
	const buf_block_t*	block)	/*!< in: block */
680
	__attribute__((pure));
681
#ifdef UNIV_DEBUG
682
/*********************************************************************//**
683
Finds a block in the buffer pool that points to a
684 685
given compressed page.
@return	buffer block pointing to the compressed page, or NULL */
686
UNIV_INTERN
687 688 689
buf_block_t*
buf_pool_contains_zip(
/*==================*/
irana's avatar
irana committed
690 691
	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
	const void*	data);		/*!< in: pointer to compressed page */
692
#endif /* UNIV_DEBUG */
693
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
694
/*********************************************************************//**
695 696
Validates the buffer pool data structure.
@return	TRUE */
697
UNIV_INTERN
osku's avatar
osku committed
698 699 700
ibool
buf_validate(void);
/*==============*/
701 702
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
703
/*********************************************************************//**
osku's avatar
osku committed
704
Prints info of the buffer pool data structure. */
705
UNIV_INTERN
osku's avatar
osku committed
706 707 708
void
buf_print(void);
/*============*/
709
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
710
#endif /* !UNIV_HOTBACKUP */
711 712 713 714 715 716 717
enum buf_page_print_flags {
	/** Do not crash at the end of buf_page_print(). */
	BUF_PAGE_PRINT_NO_CRASH	= 1,
	/** Do not print the full page dump. */
	BUF_PAGE_PRINT_NO_FULL = 2
};

718
/********************************************************************//**
osku's avatar
osku committed
719
Prints a page to stderr. */
720
UNIV_INTERN
osku's avatar
osku committed
721 722 723
void
buf_page_print(
/*===========*/
724
	const byte*	read_buf,	/*!< in: a database page */
725
	ulint		zip_size,	/*!< in: compressed page size, or
marko's avatar
marko committed
726
					0 for uncompressed pages */
727 728 729 730
	ulint		flags)		/*!< in: 0 or
					BUF_PAGE_PRINT_NO_CRASH or
					BUF_PAGE_PRINT_NO_FULL */
	__attribute__((nonnull));
731
/********************************************************************//**
732 733
Decompress a block.
@return	TRUE if successful */
734 735 736 737
UNIV_INTERN
ibool
buf_zip_decompress(
/*===============*/
738 739
	buf_block_t*	block,	/*!< in/out: block */
	ibool		check);	/*!< in: TRUE=verify the page checksum */
740
#ifndef UNIV_HOTBACKUP
741
#ifdef UNIV_DEBUG
742
/*********************************************************************//**
743 744
Returns the number of latched pages in the buffer pool.
@return	number of latched pages */
745
UNIV_INTERN
osku's avatar
osku committed
746 747 748
ulint
buf_get_latched_pages_number(void);
/*==============================*/
749
#endif /* UNIV_DEBUG */
750
/*********************************************************************//**
751 752
Returns the number of pending buf pool ios.
@return	number of pending I/O operations */
753
UNIV_INTERN
osku's avatar
osku committed
754 755 756
ulint
buf_get_n_pending_ios(void);
/*=======================*/
757
/*********************************************************************//**
osku's avatar
osku committed
758
Prints info of the buffer i/o. */
759
UNIV_INTERN
osku's avatar
osku committed
760 761 762
void
buf_print_io(
/*=========*/
763
	FILE*	file);	/*!< in: file where to print */
764 765 766 767 768 769 770 771 772 773 774 775
/*******************************************************************//**
Collect buffer pool stats information for a buffer pool. Also
record aggregated stats if there are more than one buffer pool
in the server */
UNIV_INTERN
void
buf_stats_get_pool_info(
/*====================*/
	buf_pool_t*		buf_pool,	/*!< in: buffer pool */
	ulint			pool_id,	/*!< in: buffer pool ID */
	buf_pool_info_t*	all_pool_info);	/*!< in/out: buffer pool info
						to fill */
776
/*********************************************************************//**
osku's avatar
osku committed
777
Returns the ratio in percents of modified pages in the buffer pool /
778 779
database pages in the buffer pool.
@return	modified page percentage ratio */
780
UNIV_INTERN
osku's avatar
osku committed
781 782 783
ulint
buf_get_modified_ratio_pct(void);
/*============================*/
784
/**********************************************************************//**
osku's avatar
osku committed
785
Refreshes the statistics used to print per-second averages. */
786
UNIV_INTERN
osku's avatar
osku committed
787
void
irana's avatar
irana committed
788 789 790 791 792 793 794 795 796
buf_refresh_io_stats(
/*=================*/
	buf_pool_t*	buf_pool);	/*!< buffer pool instance */
/**********************************************************************//**
Refreshes the statistics used to print per-second averages. */
UNIV_INTERN
void
buf_refresh_io_stats_all(void);
/*=================*/
797
/*********************************************************************//**
798 799
Asserts that all file pages in the buffer are in a replaceable state.
@return	TRUE */
800
UNIV_INTERN
osku's avatar
osku committed
801 802 803
ibool
buf_all_freed(void);
/*===============*/
804
/*********************************************************************//**
osku's avatar
osku committed
805
Checks that there currently are no pending i/o-operations for the buffer
806
pool.
807
@return	number of pending i/o operations */
808
UNIV_INTERN
809 810 811
ulint
buf_pool_check_num_pending_io(void);
/*===============================*/
812
/*********************************************************************//**
osku's avatar
osku committed
813 814 815
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. */
816
UNIV_INTERN
osku's avatar
osku committed
817 818 819
void
buf_pool_invalidate(void);
/*=====================*/
820
#endif /* !UNIV_HOTBACKUP */
osku's avatar
osku committed
821 822 823 824 825 826

/*========================================================================
--------------------------- LOWER LEVEL ROUTINES -------------------------
=========================================================================*/

#ifdef UNIV_SYNC_DEBUG
827
/*********************************************************************//**
osku's avatar
osku committed
828 829 830 831 832
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
833 834
buf_block_dbg_add_level(
/*====================*/
835
	buf_block_t*	block,	/*!< in: buffer page
836
				where we have acquired latch */
837
	ulint		level);	/*!< in: latching order level */
838 839
#else /* UNIV_SYNC_DEBUG */
# define buf_block_dbg_add_level(block, level) /* nothing */
osku's avatar
osku committed
840
#endif /* UNIV_SYNC_DEBUG */
841
/*********************************************************************//**
842 843
Gets the state of a block.
@return	state */
844
UNIV_INLINE
845
enum buf_page_state
846 847
buf_page_get_state(
/*===============*/
848
	const buf_page_t*	bpage);	/*!< in: pointer to the control block */
849
/*********************************************************************//**
850 851
Gets the state of a block.
@return	state */
852 853
UNIV_INLINE
enum buf_page_state
854 855
buf_block_get_state(
/*================*/
856
	const buf_block_t*	block)	/*!< in: pointer to the control block */
857
	__attribute__((pure));
858
/*********************************************************************//**
859 860 861
Sets the state of a block. */
UNIV_INLINE
void
862 863
buf_page_set_state(
/*===============*/
864 865
	buf_page_t*		bpage,	/*!< in/out: pointer to control block */
	enum buf_page_state	state);	/*!< in: state */
866
/*********************************************************************//**
867 868 869
Sets the state of a block. */
UNIV_INLINE
void
870 871
buf_block_set_state(
/*================*/
872 873
	buf_block_t*		block,	/*!< in/out: pointer to control block */
	enum buf_page_state	state);	/*!< in: state */
874
/*********************************************************************//**
875 876
Determines if a block is mapped to a tablespace.
@return	TRUE if mapped */
877 878 879 880
UNIV_INLINE
ibool
buf_page_in_file(
/*=============*/
881
	const buf_page_t*	bpage)	/*!< in: pointer to control block */
882
	__attribute__((pure));
883
#ifndef UNIV_HOTBACKUP
884
/*********************************************************************//**
885 886
Determines if a block should be on unzip_LRU list.
@return	TRUE if block belongs to unzip_LRU */
887 888 889 890
UNIV_INLINE
ibool
buf_page_belongs_to_unzip_LRU(
/*==========================*/
891
	const buf_page_t*	bpage)	/*!< in: pointer to control block */
892
	__attribute__((pure));
893

894
/*********************************************************************//**
895 896
Gets the mutex of a block.
@return	pointer to mutex protecting bpage */
897 898 899
UNIV_INLINE
mutex_t*
buf_page_get_mutex(
900
/*===============*/
901
	const buf_page_t*	bpage)	/*!< in: pointer to control block */
902 903
	__attribute__((pure));

904
/*********************************************************************//**
905 906
Get the flush type of a page.
@return	flush type */
907 908 909 910
UNIV_INLINE
enum buf_flush
buf_page_get_flush_type(
/*====================*/
911
	const buf_page_t*	bpage)	/*!< in: buffer page */
912
	__attribute__((pure));
913
/*********************************************************************//**
914 915 916 917 918
Set the flush type of a page. */
UNIV_INLINE
void
buf_page_set_flush_type(
/*====================*/
919 920
	buf_page_t*	bpage,		/*!< in: buffer page */
	enum buf_flush	flush_type);	/*!< in: flush type */
921
/*********************************************************************//**
922 923 924 925 926
Map a block to a file page. */
UNIV_INLINE
void
buf_block_set_file_page(
/*====================*/
927 928 929
	buf_block_t*		block,	/*!< in/out: pointer to control block */
	ulint			space,	/*!< in: tablespace id */
	ulint			page_no);/*!< in: page number */
930
/*********************************************************************//**
931 932
Gets the io_fix state of a block.
@return	io_fix state */
933 934 935 936
UNIV_INLINE
enum buf_io_fix
buf_page_get_io_fix(
/*================*/
937
	const buf_page_t*	bpage)	/*!< in: pointer to the control block */
938
	__attribute__((pure));
939
/*********************************************************************//**
940 941
Gets the io_fix state of a block.
@return	io_fix state */
942 943 944 945
UNIV_INLINE
enum buf_io_fix
buf_block_get_io_fix(
/*================*/
946
	const buf_block_t*	block)	/*!< in: pointer to the control block */
947
	__attribute__((pure));
948
/*********************************************************************//**
949 950 951 952 953
Sets the io_fix state of a block. */
UNIV_INLINE
void
buf_page_set_io_fix(
/*================*/
954 955
	buf_page_t*	bpage,	/*!< in/out: control block */
	enum buf_io_fix	io_fix);/*!< in: io_fix state */
956
/*********************************************************************//**
957 958 959 960 961
Sets the io_fix state of a block. */
UNIV_INLINE
void
buf_block_set_io_fix(
/*=================*/
962 963
	buf_block_t*	block,	/*!< in/out: control block */
	enum buf_io_fix	io_fix);/*!< in: io_fix state */
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
/*********************************************************************//**
Makes a block sticky. A sticky block implies that even after we release
the buf_pool->mutex and the block->mutex:
* it cannot be removed from the flush_list
* the block descriptor cannot be relocated
* it cannot be removed from the LRU list
Note that:
* the block can still change its position in the LRU list
* the next and previous pointers can change. */
UNIV_INLINE
void
buf_page_set_sticky(
/*================*/
	buf_page_t*	bpage);	/*!< in/out: control block */
/*********************************************************************//**
Removes stickiness of a block. */
UNIV_INLINE
void
buf_page_unset_sticky(
/*==================*/
	buf_page_t*	bpage);	/*!< in/out: control block */
985
/********************************************************************//**
986 987 988 989 990 991
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(
/*==================*/
992
	const buf_page_t*	bpage)	/*!< control block being relocated */
993
	__attribute__((pure));
994

995
/*********************************************************************//**
996 997
Determine if a block has been flagged old.
@return	TRUE if old */
998 999 1000 1001
UNIV_INLINE
ibool
buf_page_is_old(
/*============*/
1002
	const buf_page_t*	bpage)	/*!< in: control block */
1003
	__attribute__((pure));
1004
/*********************************************************************//**
1005 1006 1007 1008 1009
Flag a block old. */
UNIV_INLINE
void
buf_page_set_old(
/*=============*/
1010 1011
	buf_page_t*	bpage,	/*!< in/out: control block */
	ibool		old);	/*!< in: old */
1012
/*********************************************************************//**
1013 1014
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 */
1015
UNIV_INLINE
1016
unsigned
1017 1018
buf_page_is_accessed(
/*=================*/
1019
	const buf_page_t*	bpage)	/*!< in: control block */
1020
	__attribute__((nonnull, pure));
1021
/*********************************************************************//**
1022 1023 1024 1025 1026
Flag a block accessed. */
UNIV_INLINE
void
buf_page_set_accessed(
/*==================*/
1027
	buf_page_t*	bpage,		/*!< in/out: control block */
1028 1029
	ulint		time_ms)	/*!< in: ut_time_ms() */
	__attribute__((nonnull));
1030
/*********************************************************************//**
1031
Gets the buf_block_t handle of a buffered file block if an uncompressed
1032 1033
page frame exists, or NULL. Note: even though bpage is not declared a
const we don't update its value. It is safe to make this pure.
1034
@return	control block, or NULL */
1035
UNIV_INLINE
1036
buf_block_t*
1037 1038
buf_page_get_block(
/*===============*/
1039
	buf_page_t*	bpage)	/*!< in: control block, or NULL */
1040
	__attribute__((pure));
1041
#endif /* !UNIV_HOTBACKUP */
1042
#ifdef UNIV_DEBUG
1043
/*********************************************************************//**
1044 1045
Gets a pointer to the memory frame of a block.
@return	pointer to the frame */
osku's avatar
osku committed
1046 1047 1048 1049
UNIV_INLINE
buf_frame_t*
buf_block_get_frame(
/*================*/
1050
	const buf_block_t*	block)	/*!< in: pointer to the control block */
1051
	__attribute__((pure));
1052
#else /* UNIV_DEBUG */
1053
# define buf_block_get_frame(block) (block)->frame
1054
#endif /* UNIV_DEBUG */
1055
/*********************************************************************//**
1056 1057
Gets the space id of a block.
@return	space id */
1058 1059 1060 1061
UNIV_INLINE
ulint
buf_page_get_space(
/*===============*/
1062
	const buf_page_t*	bpage)	/*!< in: pointer to the control block */
1063
	__attribute__((pure));
1064
/*********************************************************************//**
1065 1066
Gets the space id of a block.
@return	space id */
osku's avatar
osku committed
1067 1068 1069 1070
UNIV_INLINE
ulint
buf_block_get_space(
/*================*/
1071
	const buf_block_t*	block)	/*!< in: pointer to the control block */
1072
	__attribute__((pure));
1073
/*********************************************************************//**
1074 1075
Gets the page number of a block.
@return	page number */
1076 1077 1078 1079
UNIV_INLINE
ulint
buf_page_get_page_no(
/*=================*/
1080
	const buf_page_t*	bpage)	/*!< in: pointer to the control block */
1081
	__attribute__((pure));
1082
/*********************************************************************//**
1083 1084
Gets the page number of a block.
@return	page number */
osku's avatar
osku committed
1085 1086 1087 1088
UNIV_INLINE
ulint
buf_block_get_page_no(
/*==================*/
1089
	const buf_block_t*	block)	/*!< in: pointer to the control block */
1090
	__attribute__((pure));
1091
/*********************************************************************//**
1092 1093
Gets the compressed page size of a block.
@return	compressed page size, or 0 */
1094 1095 1096 1097
UNIV_INLINE
ulint
buf_page_get_zip_size(
/*==================*/
1098
	const buf_page_t*	bpage)	/*!< in: pointer to the control block */
1099
	__attribute__((pure));
1100
/*********************************************************************//**
1101 1102
Gets the compressed page size of a block.
@return	compressed page size, or 0 */
1103 1104 1105 1106
UNIV_INLINE
ulint
buf_block_get_zip_size(
/*===================*/
1107
	const buf_block_t*	block)	/*!< in: pointer to the control block */
1108
	__attribute__((pure));
1109
/*********************************************************************//**
1110 1111
Gets the compressed page descriptor corresponding to an uncompressed page
if applicable. */
1112 1113
#define buf_block_get_page_zip(block) \
	(UNIV_LIKELY_NULL((block)->page.zip.data) ? &(block)->page.zip : NULL)
1114
#ifndef UNIV_HOTBACKUP
1115
/*******************************************************************//**
1116 1117
Gets the block to whose frame the pointer is pointing to.
@return	pointer to block, never NULL */
1118 1119
UNIV_INTERN
buf_block_t*
osku's avatar
osku committed
1120 1121
buf_block_align(
/*============*/
1122
	const byte*	ptr);	/*!< in: pointer to a frame */
1123
/********************************************************************//**
1124
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
1125 1126
the buf_block_t itself or a member of it
@return	TRUE if ptr belongs to a buf_block_t struct */
1127 1128 1129 1130
UNIV_INTERN
ibool
buf_pointer_is_block_field(
/*=======================*/
1131
	const void*		ptr);	/*!< in: pointer not
1132
					dereferenced */
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
/** 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))
1143

1144
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
1145
/*********************************************************************//**
1146
Gets the compressed page descriptor corresponding to an uncompressed page
1147 1148
if applicable.
@return	compressed page descriptor, or NULL */
1149
UNIV_INLINE
1150
const page_zip_des_t*
1151 1152
buf_frame_get_page_zip(
/*===================*/
1153
	const byte*	ptr);	/*!< in: pointer to the page */
1154
#endif /* UNIV_DEBUG || UNIV_ZIP_DEBUG */
1155
/********************************************************************//**
osku's avatar
osku committed
1156 1157 1158 1159 1160 1161 1162
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
1163 1164
and the lock released later.
@return	pointer to the block or NULL */
1165
UNIV_INTERN
1166
buf_page_t*
osku's avatar
osku committed
1167 1168
buf_page_init_for_read(
/*===================*/
1169 1170 1171 1172 1173 1174
	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
osku's avatar
osku committed
1175 1176
				version of the tablespace in case we have done
				DISCARD + IMPORT */
1177
	ulint		offset);/*!< in: page number */
1178
/********************************************************************//**
osku's avatar
osku committed
1179
Completes an asynchronous read or write request of a file page to or from
1180 1181
the buffer pool.
@return TRUE if successful */
1182
UNIV_INTERN
1183
ibool
osku's avatar
osku committed
1184 1185
buf_page_io_complete(
/*=================*/
1186
	buf_page_t*	bpage);	/*!< in: pointer to the block in question */
1187
/********************************************************************//**
osku's avatar
osku committed
1188
Calculates a folded value of a file page address to use in the page hash
1189 1190
table.
@return	the folded value */
osku's avatar
osku committed
1191 1192 1193 1194
UNIV_INLINE
ulint
buf_page_address_fold(
/*==================*/
1195 1196
	ulint	space,	/*!< in: space id */
	ulint	offset)	/*!< in: offset of the page within space */
1197
	__attribute__((const));
1198 1199 1200 1201 1202 1203 1204 1205 1206
/********************************************************************//**
Calculates the index of a buffer pool to the buf_pool[] array.
@return	the position of the buffer pool in buf_pool[] */
UNIV_INLINE
ulint
buf_pool_index(
/*===========*/
	const buf_pool_t*	buf_pool)	/*!< in: buffer pool */
	__attribute__((nonnull, const));
1207
/******************************************************************//**
irana's avatar
irana committed
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237
Returns the buffer pool instance given a page instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_bpage(
/*================*/
	const buf_page_t*	bpage); /*!< in: buffer pool page */
/******************************************************************//**
Returns the buffer pool instance given a block instance
@return buf_pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_block(
/*================*/
	const buf_block_t*	block); /*!< in: block */
/******************************************************************//**
Returns the buffer pool instance given space and offset of page
@return buffer pool */
UNIV_INLINE
buf_pool_t*
buf_pool_get(
/*==========*/
	ulint	space,	/*!< in: space id */
	ulint	offset);/*!< in: offset of the page within space */
/******************************************************************//**
Returns the buffer pool instance given its array index
@return buffer pool */
UNIV_INLINE
buf_pool_t*
buf_pool_from_array(
1238 1239 1240
/*================*/
	ulint	index);		/*!< in: array index to get
				buffer pool instance from */
irana's avatar
irana committed
1241
/******************************************************************//**
1242 1243
Returns the control block of a file page, NULL if not found.
@return	block, NULL if not found */
osku's avatar
osku committed
1244
UNIV_INLINE
1245
buf_page_t*
1246 1247
buf_page_hash_get_low(
/*==================*/
irana's avatar
irana committed
1248 1249 1250 1251 1252 1253
	buf_pool_t*	buf_pool,	/*!< buffer pool instance */
	ulint		space,		/*!< in: space id */
	ulint		offset,		/*!< in: offset of the page
					within space */
	ulint		fold);		/*!< in: buf_page_address_fold(
					space, offset) */
1254 1255 1256 1257 1258
/******************************************************************//**
Returns the control block of a file page, NULL if not found.
@return	block, NULL if not found or not a real control block */
UNIV_INLINE
buf_page_t*
osku's avatar
osku committed
1259 1260
buf_page_hash_get(
/*==============*/
irana's avatar
irana committed
1261 1262 1263 1264
	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
	ulint		space,		/*!< in: space id */
	ulint		offset);	/*!< in: offset of the page
					within space */
1265
/******************************************************************//**
1266
Returns the control block of a file page, NULL if not found
1267 1268
or an uncompressed page frame does not exist.
@return	block, NULL if not found */
1269 1270 1271 1272
UNIV_INLINE
buf_block_t*
buf_block_hash_get(
/*===============*/
irana's avatar
irana committed
1273 1274 1275 1276
	buf_pool_t*	buf_pool,	/*!< in: buffer pool instance */
	ulint		space,		/*!< in: space id */
	ulint		offset);	/*!< in: offset of the page
					within space */
1277
/*********************************************************************//**
1278 1279
Gets the current length of the free list of buffer blocks.
@return	length of the free list */
1280
UNIV_INTERN
osku's avatar
osku committed
1281 1282 1283
ulint
buf_get_free_list_len(void);
/*=======================*/
1284

1285
/********************************************************************//**
1286 1287
Determine if a block is a sentinel for a buffer pool watch.
@return	TRUE if a sentinel for a buffer pool watch, FALSE if not */
1288
UNIV_INTERN
1289
ibool
irana's avatar
irana committed
1290 1291 1292 1293
buf_pool_watch_is_sentinel(
/*=======================*/
	buf_pool_t*		buf_pool,	/*!< buffer pool instance */
	const buf_page_t*	bpage)		/*!< in: block */
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
	__attribute__((nonnull, warn_unused_result));
/****************************************************************//**
Add watch for the given page to be read in. Caller must have the buffer pool
@return NULL if watch set, block if the page is in the buffer pool */
UNIV_INTERN
buf_page_t*
buf_pool_watch_set(
/*===============*/
	ulint	space,	/*!< in: space id */
	ulint	offset,	/*!< in: page number */
	ulint	fold)	/*!< in: buf_page_address_fold(space, offset) */
	__attribute__((warn_unused_result));
/****************************************************************//**
Stop watching if the page has been read in.
buf_pool_watch_set(space,offset) must have returned NULL before. */
1309 1310
UNIV_INTERN
void
1311 1312 1313 1314 1315 1316 1317 1318 1319
buf_pool_watch_unset(
/*=================*/
	ulint	space,	/*!< in: space id */
	ulint	offset);/*!< in: page number */
/****************************************************************//**
Check if the page has been read in.
This may only be called after buf_pool_watch_set(space,offset)
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
@return	FALSE if the given page was not read in, TRUE if it was */
1320
UNIV_INTERN
1321
ibool
1322
buf_pool_watch_occurred(
1323
/*====================*/
1324 1325 1326
	ulint	space,	/*!< in: space id */
	ulint	offset)	/*!< in: page number */
	__attribute__((warn_unused_result));
irana's avatar
irana committed
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
/********************************************************************//**
Get total buffer pool statistics. */
UNIV_INTERN
void
buf_get_total_list_len(
/*===================*/
	ulint*		LRU_len,	/*!< out: length of all LRU lists */
	ulint*		free_len,	/*!< out: length of all free lists */
	ulint*		flush_list_len);/*!< out: length of all flush lists */
/********************************************************************//**
Get total buffer pool statistics. */
UNIV_INTERN
void
buf_get_total_stat(
/*===============*/
	buf_pool_stat_t*tot_stat);	/*!< out: buffer pool stats */
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
/*********************************************************************//**
Get the nth chunk's buffer block in the specified buffer pool.
@return the nth chunk's buffer block. */
UNIV_INLINE
buf_block_t*
buf_get_nth_chunk_block(
/*====================*/
	const buf_pool_t* buf_pool,	/*!< in: buffer pool instance */
	ulint		n,		/*!< in: nth chunk in the buffer pool */
	ulint*		chunk_size);	/*!< in: chunk size */
irana's avatar
irana committed
1353

1354
#endif /* !UNIV_HOTBACKUP */
1355

1356
/** The common buffer control block structure
1357 1358
for compressed and uncompressed frames */

1359 1360 1361
/** Number of bits used for buffer page states. */
#define BUF_PAGE_STATE_BITS	3

1362
struct buf_page_struct{
1363 1364 1365
	/** @name General fields
	None of these bit-fields must be modified without holding
	buf_page_get_mutex() [buf_block_struct::mutex or
irana's avatar
irana committed
1366
	buf_pool->zip_mutex], since they can be stored in the same
1367
	machine word.  Some of these fields are additionally protected
irana's avatar
irana committed
1368
	by buf_pool->mutex. */
1369 1370 1371
	/* @{ */

	unsigned	space:32;	/*!< tablespace id; also protected
irana's avatar
irana committed
1372
					by buf_pool->mutex. */
1373
	unsigned	offset:32;	/*!< page number; also protected
irana's avatar
irana committed
1374
					by buf_pool->mutex. */
1375

1376 1377
	unsigned	state:BUF_PAGE_STATE_BITS;
					/*!< state of the control block; also
irana's avatar
irana committed
1378
					protected by buf_pool->mutex.
1379 1380 1381
					State transitions from
					BUF_BLOCK_READY_FOR_USE to
					BUF_BLOCK_MEMORY need not be
1382 1383
					protected by buf_page_get_mutex().
					@see enum buf_page_state */
1384
#ifndef UNIV_HOTBACKUP
1385
	unsigned	flush_type:2;	/*!< if this block is currently being
1386
					flushed to disk, this tells the
1387 1388 1389
					flush_type.
					@see enum buf_flush */
	unsigned	io_fix:2;	/*!< type of pending I/O operation;
irana's avatar
irana committed
1390
					also protected by buf_pool->mutex
1391
					@see enum buf_io_fix */
1392
	unsigned	buf_fix_count:19;/*!< count of how manyfold this block
1393
					is currently bufferfixed */
1394 1395 1396 1397 1398
	unsigned	buf_pool_index:6;/*!< index number of the buffer pool
					that this block belongs to */
# if MAX_BUFFER_POOLS > 64
#  error "MAX_BUFFER_POOLS > 64; redefine buf_pool_index:6"
# endif
1399
	/* @} */
1400
#endif /* !UNIV_HOTBACKUP */
1401
	page_zip_des_t	zip;		/*!< compressed page; zip.data
1402
					(but not the data it points to) is
1403
					also protected by buf_pool->mutex;
1404 1405
					state == BUF_BLOCK_ZIP_PAGE and
					zip.data == NULL means an active
1406
					buf_pool->watch */
1407
#ifndef UNIV_HOTBACKUP
1408
	buf_page_t*	hash;		/*!< node used in chaining to
1409 1410
					buf_pool->page_hash or
					buf_pool->zip_hash */
1411
#ifdef UNIV_DEBUG
1412 1413
	ibool		in_page_hash;	/*!< TRUE if in buf_pool->page_hash */
	ibool		in_zip_hash;	/*!< TRUE if in buf_pool->zip_hash */
1414
#endif /* UNIV_DEBUG */
1415

1416
	/** @name Page flushing fields
1417
	All these are protected by buf_pool->mutex. */
1418
	/* @{ */
1419

1420
	UT_LIST_NODE_T(buf_page_t) list;
1421
					/*!< based on state, this is a
inaam's avatar
inaam committed
1422
					list node, protected either by
1423 1424 1425 1426
					buf_pool->mutex or by
					buf_pool->flush_list_mutex,
					in one of the following lists in
					buf_pool:
1427

1428 1429 1430 1431
					- BUF_BLOCK_NOT_USED:	free
					- BUF_BLOCK_FILE_PAGE:	flush_list
					- BUF_BLOCK_ZIP_DIRTY:	flush_list
					- BUF_BLOCK_ZIP_PAGE:	zip_clean
1432 1433
					- BUF_BLOCK_ZIP_FREE:	zip_free[]

inaam's avatar
inaam committed
1434 1435
					If bpage is part of flush_list
					then the node pointers are
1436
					covered by buf_pool->flush_list_mutex.
inaam's avatar
inaam committed
1437
					Otherwise these pointers are
1438
					protected by buf_pool->mutex.
inaam's avatar
inaam committed
1439

1440 1441 1442 1443 1444 1445 1446 1447
					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. */

1448
#ifdef UNIV_DEBUG
1449
	ibool		in_flush_list;	/*!< TRUE if in buf_pool->flush_list;
1450 1451 1452
					when buf_pool->flush_list_mutex is
					free, the following should hold:
					in_flush_list
1453
					== (state == BUF_BLOCK_FILE_PAGE
inaam's avatar
inaam committed
1454 1455 1456
					    || state == BUF_BLOCK_ZIP_DIRTY)
					Writes to this field must be
					covered by both block->mutex
1457
					and buf_pool->flush_list_mutex. Hence
inaam's avatar
inaam committed
1458 1459
					reads can happen while holding
					any one of the two mutexes */
1460
	ibool		in_free_list;	/*!< TRUE if in buf_pool->free; when
1461
					buf_pool->mutex is free, the following
1462 1463
					should hold: in_free_list
					== (state == BUF_BLOCK_NOT_USED) */
1464
#endif /* UNIV_DEBUG */
1465
	ib_uint64_t	newest_modification;
1466 1467 1468
					/*!< log sequence number of
					the youngest modification to
					this block, zero if not
inaam's avatar
inaam committed
1469 1470
					modified. Protected by block
					mutex */
1471
	ib_uint64_t	oldest_modification;
1472 1473 1474 1475 1476 1477
					/*!< 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
inaam's avatar
inaam committed
1478 1479 1480
					modifications are on disk.
					Writes to this field must be
					covered by both block->mutex
1481
					and buf_pool->flush_list_mutex. Hence
inaam's avatar
inaam committed
1482 1483
					reads can happen while holding
					any one of the two mutexes */
1484 1485
	/* @} */
	/** @name LRU replacement algorithm fields
irana's avatar
irana committed
1486 1487
	These fields are protected by buf_pool->mutex only (not
	buf_pool->zip_mutex or buf_block_struct::mutex). */
1488
	/* @{ */
1489 1490

	UT_LIST_NODE_T(buf_page_t) LRU;
1491
					/*!< node of the LRU list */
1492
#ifdef UNIV_DEBUG
1493 1494 1495
	ibool		in_LRU_list;	/*!< TRUE if the page is in
					the LRU list; used in
					debugging */
1496
#endif /* UNIV_DEBUG */
1497
	unsigned	old:1;		/*!< TRUE if the block is in the old
1498
					blocks in buf_pool->LRU_old */
1499
	unsigned	freed_page_clock:31;/*!< the value of
1500 1501 1502 1503 1504 1505 1506
					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 */
1507 1508 1509
	unsigned	access_time:32;	/*!< time of first access, or
					0 if the block was never accessed
					in the buffer pool */
1510
	/* @} */
1511
# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
1512
	ibool		file_page_was_freed;
1513
					/*!< this is set to TRUE when fsp
1514
					frees a page in buffer pool */
1515
# endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
1516
#endif /* !UNIV_HOTBACKUP */
1517 1518
};

1519
/** The buffer control block structure */
osku's avatar
osku committed
1520 1521 1522

struct buf_block_struct{

1523 1524
	/** @name General fields */
	/* @{ */
osku's avatar
osku committed
1525

1526
	buf_page_t	page;		/*!< page information; this must
1527 1528 1529
					be the first field, so that
					buf_pool->page_hash can point
					to buf_page_t or buf_block_t */
1530
	byte*		frame;		/*!< pointer to buffer frame which
1531 1532 1533 1534
					is of size UNIV_PAGE_SIZE, and
					aligned to an address divisible by
					UNIV_PAGE_SIZE */
#ifndef UNIV_HOTBACKUP
1535
	UT_LIST_NODE_T(buf_block_t) unzip_LRU;
1536
					/*!< node of the decompressed LRU list;
1537 1538 1539 1540
					a block is in the unzip_LRU list
					if page.state == BUF_BLOCK_FILE_PAGE
					and page.zip.data != NULL */
#ifdef UNIV_DEBUG
1541
	ibool		in_unzip_LRU_list;/*!< TRUE if the page is in the
1542 1543 1544
					decompressed LRU list;
					used in debugging */
#endif /* UNIV_DEBUG */
1545
	mutex_t		mutex;		/*!< mutex protecting this block:
1546 1547 1548 1549 1550
					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 */
1551
	rw_lock_t	lock;		/*!< read-write lock of the buffer
osku's avatar
osku committed
1552
					frame */
1553
	unsigned	lock_hash_val:32;/*!< hashed value of the page address
1554 1555
					in the record lock hash table;
					protected by buf_block_t::lock
irana's avatar
irana committed
1556
					(or buf_block_t::mutex, buf_pool->mutex
1557 1558 1559 1560
				        in buf_page_get_gen(),
					buf_page_init_for_read()
					and buf_page_create()) */
	ibool		check_index_page_at_flush;
1561
					/*!< TRUE if we know that this is
osku's avatar
osku committed
1562 1563 1564 1565 1566
					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
1567 1568
					we do not keep track of all pages;
					NOT protected by any mutex */
1569 1570 1571
	/* @} */
	/** @name Optimistic search field */
	/* @{ */
osku's avatar
osku committed
1572

1573
	ib_uint64_t	modify_clock;	/*!< this clock is incremented every
osku's avatar
osku committed
1574 1575 1576 1577 1578 1579 1580 1581 1582 1583
					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 */
1584 1585 1586 1587
	/* @} */
	/** @name Hash search fields (unprotected)
	NOTE that these fields are NOT protected by any semaphore! */
	/* @{ */
osku's avatar
osku committed
1588

1589
	ulint		n_hash_helps;	/*!< counter which controls building
osku's avatar
osku committed
1590
					of a new hash index for the page */
1591
	ulint		n_fields;	/*!< recommended prefix length for hash
osku's avatar
osku committed
1592
					search: number of full fields */
1593
	ulint		n_bytes;	/*!< recommended prefix: number of bytes
osku's avatar
osku committed
1594
					in an incomplete field */
1595
	ibool		left_side;	/*!< TRUE or FALSE, depending on
osku's avatar
osku committed
1596 1597 1598
					whether the leftmost record of several
					records with the same prefix should be
					indexed in the hash index */
1599
	/* @} */
1600

1601
	/** @name Hash search fields
1602
	These 5 fields may only be modified when we have
1603
	an x-latch on btr_search_latch AND
1604 1605
	- 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.
1606 1607

	An exception to this is when we init or create a page
1608 1609 1610 1611
	in the buffer pool in buf0buf.c.

	Another exception is that assigning block->index = NULL
	is allowed whenever holding an x-latch on btr_search_latch. */
osku's avatar
osku committed
1612

1613 1614
	/* @{ */

1615
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
1616
	ulint		n_pointers;	/*!< used in debugging: the number of
osku's avatar
osku committed
1617 1618
					pointers in the adaptive hash index
					pointing to this frame */
1619
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
1620
	unsigned	curr_n_fields:10;/*!< prefix length for hash indexing:
osku's avatar
osku committed
1621
					number of full fields */
1622 1623 1624
	unsigned	curr_n_bytes:15;/*!< number of bytes in hash
					indexing */
	unsigned	curr_left_side:1;/*!< TRUE or FALSE in hash indexing */
1625 1626 1627 1628 1629 1630 1631 1632 1633
	dict_index_t*	index;		/*!< Index for which the
					adaptive hash index has been
					created, or NULL if the page
					does not exist in the
					index. Note that it does not
					guarantee that the index is
					complete, though: there may
					have been hash collisions,
					record deletions, etc. */
1634 1635 1636 1637 1638
	/* @} */
# ifdef UNIV_SYNC_DEBUG
	/** @name Debug fields */
	/* @{ */
	rw_lock_t	debug_latch;	/*!< in the debug version, each thread
osku's avatar
osku committed
1639 1640 1641
					which bufferfixes the block acquires
					an s-latch here; so we can use the
					debug utilities in sync0rw */
1642 1643
	/* @} */
# endif
1644
#endif /* !UNIV_HOTBACKUP */
osku's avatar
osku committed
1645 1646
};

1647 1648 1649
/** Check if a buf_block_t object is in a valid state
@param block	buffer block
@return		TRUE if valid */
1650
#define buf_block_state_valid(block)				\
1651 1652
(buf_block_get_state(block) >= BUF_BLOCK_NOT_USED		\
 && (buf_block_get_state(block) <= BUF_BLOCK_REMOVE_HASH))
osku's avatar
osku committed
1653

1654
#ifndef UNIV_HOTBACKUP
1655
/**********************************************************************//**
1656
Compute the hash fold value for blocks in buf_pool->zip_hash. */
1657
/* @{ */
1658 1659 1660
#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))
1661
/* @} */
1662

1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674
/** @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 */
1675 1676
	ulint	n_ra_pages_read_rnd;/*!< number of pages read in
				as part of random read ahead */
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689
	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() */
};

irana's avatar
irana committed
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699
/** Statistics of buddy blocks of a given size. */
struct buf_buddy_stat_struct {
	/** Number of blocks allocated from the buddy system. */
	ulint		used;
	/** Number of blocks relocated by the buddy system. */
	ib_uint64_t	relocated;
	/** Total duration of block relocations, in microseconds. */
	ib_uint64_t	relocated_usec;
};

1700 1701 1702 1703
/** @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! */
osku's avatar
osku committed
1704 1705 1706

struct buf_pool_struct{

1707 1708
	/** @name General fields */
	/* @{ */
irana's avatar
irana committed
1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727
	mutex_t		mutex;		/*!< Buffer pool mutex of this
					instance */
	mutex_t		zip_mutex;	/*!< Zip mutex of this buffer
					pool instance, protects compressed
					only pages (of type buf_page_t, not
					buf_block_t */
	ulint		instance_no;	/*!< Array index of this buffer
					pool instance */
	ulint		old_pool_size;  /*!< Old pool size in bytes */
	ulint		curr_pool_size;	/*!< Current pool size in bytes */
	ulint		LRU_old_ratio;  /*!< Reserve this much of the buffer
					pool for "old" blocks */
#ifdef UNIV_DEBUG
	ulint		buddy_n_frames; /*!< Number of frames allocated from
					the buffer pool to the buddy system */
#endif
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
	ulint		mutex_exit_forbidden; /*!< Forbid release mutex */
#endif
1728 1729 1730 1731
	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
1732 1733 1734
					buf_block_t file pages,
					buf_page_in_file() == TRUE,
					indexed by (space_id, offset) */
1735
	hash_table_t*	zip_hash;	/*!< hash table of buf_block_t blocks
1736 1737 1738
					whose frames are allocated to the
					zip buddy system,
					indexed by block->frame */
irana's avatar
irana committed
1739 1740
	ulint		n_pend_reads;	/*!< number of pending read
					operations */
1741
	ulint		n_pend_unzip;	/*!< number of pending decompressions */
osku's avatar
osku committed
1742

1743 1744
	time_t		last_printout_time;
					/*!< when buf_print_io was last time
osku's avatar
osku committed
1745
					called */
irana's avatar
irana committed
1746 1747 1748
	buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES + 1];
					/*!< Statistics of buddy system,
					indexed by block size */
1749 1750 1751
	buf_pool_stat_t	stat;		/*!< current statistics */
	buf_pool_stat_t	old_stat;	/*!< old statistics */

1752
	/* @} */
1753

1754
	/** @name Page flushing algorithm fields */
1755

1756
	/* @{ */
osku's avatar
osku committed
1757

inaam's avatar
inaam committed
1758 1759 1760 1761 1762 1763 1764
	mutex_t		flush_list_mutex;/*!< mutex protecting the
					flush list access. This mutex
					protects flush_list, flush_rbt
					and bpage::list pointers when
					the bpage is on flush_list. It
					also protects writes to
					bpage::oldest_modification */
1765
	UT_LIST_BASE_NODE_T(buf_page_t) flush_list;
1766
					/*!< base node of the modified block
osku's avatar
osku committed
1767
					list */
1768
	ibool		init_flush[BUF_FLUSH_N_TYPES];
1769
					/*!< this is TRUE when a flush of the
osku's avatar
osku committed
1770
					given type is being initialized */
1771
	ulint		n_flush[BUF_FLUSH_N_TYPES];
1772
					/*!< this is the number of pending
osku's avatar
osku committed
1773
					writes in the given flush type */
1774
	os_event_t	no_flush[BUF_FLUSH_N_TYPES];
1775 1776 1777 1778
					/*!< this is in the set state
					when there is no flush batch
					of the given type running */
	ib_rbt_t*	flush_rbt;	/*!< a red-black tree is used
inaam's avatar
inaam committed
1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789
					exclusively during recovery to
					speed up insertions in the
					flush_list. This tree contains
					blocks in order of
					oldest_modification LSN and is
					kept in sync with the
					flush_list.
					Each member of the tree MUST
					also be on the flush_list.
					This tree is relevant only in
					recovery and is set to NULL
inaam's avatar
inaam committed
1790 1791
					once the recovery is over.
					Protected by flush_list_mutex */
1792 1793 1794 1795 1796 1797 1798 1799 1800 1801
	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,
osku's avatar
osku committed
1802 1803 1804
					this is incremented by one; this is
					set to zero when a buffer block is
					allocated */
1805
	/* @} */
1806

1807 1808
	/** @name LRU replacement algorithm fields */
	/* @{ */
osku's avatar
osku committed
1809

1810
	UT_LIST_BASE_NODE_T(buf_page_t) free;
1811 1812
					/*!< base node of the free
					block list */
1813
	UT_LIST_BASE_NODE_T(buf_page_t) LRU;
1814
					/*!< base node of the LRU list */
1815
	buf_page_t*	LRU_old;	/*!< pointer to the about
1816
					LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
1817 1818 1819
					oldest blocks in the LRU list;
					NULL if LRU length less than
					BUF_LRU_OLD_MIN_LEN;
1820 1821
					NOTE: when LRU_old != NULL, its length
					should always equal LRU_old_len */
1822
	ulint		LRU_old_len;	/*!< length of the LRU list from
osku's avatar
osku committed
1823 1824 1825
					the block to which LRU_old points
					onward, including that block;
					see buf0lru.c for the restrictions
1826
					on this value; 0 if LRU_old == NULL;
1827 1828
					NOTE: LRU_old_len must be adjusted
					whenever LRU_old shrinks or grows! */
1829

1830
	UT_LIST_BASE_NODE_T(buf_block_t) unzip_LRU;
1831 1832 1833 1834 1835 1836 1837 1838 1839
					/*!< 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. */
	/* @{ */
1840
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1841
	UT_LIST_BASE_NODE_T(buf_page_t)	zip_clean;
1842
					/*!< unmodified compressed pages */
1843
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1844
	UT_LIST_BASE_NODE_T(buf_page_t) zip_free[BUF_BUDDY_SIZES];
1845
					/*!< buddy free lists */
irana's avatar
irana committed
1846 1847 1848 1849 1850 1851

	buf_page_t			watch[BUF_POOL_WATCH_SIZE];
					/*!< Sentinel records for buffer
					pool watches. Protected by
				       	buf_pool->mutex. */

1852 1853
#if BUF_BUDDY_HIGH != UNIV_PAGE_SIZE
# error "BUF_BUDDY_HIGH != UNIV_PAGE_SIZE"
1854 1855 1856 1857
#endif
#if BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE
# error "BUF_BUDDY_LOW > PAGE_ZIP_MIN_SIZE"
#endif
1858
	/* @} */
osku's avatar
osku committed
1859 1860
};

1861 1862
/** @name Accessors for buf_pool->mutex.
Use these instead of accessing buf_pool->mutex directly. */
1863
/* @{ */
1864

1865
/** Test if a buffer pool mutex is owned. */
irana's avatar
irana committed
1866
#define buf_pool_mutex_own(b) mutex_own(&b->mutex)
1867
/** Acquire a buffer pool mutex. */
irana's avatar
irana committed
1868 1869 1870
#define buf_pool_mutex_enter(b) do {		\
	ut_ad(!mutex_own(&b->zip_mutex));	\
	mutex_enter(&b->mutex);		\
1871
} while (0)
1872

inaam's avatar
inaam committed
1873
/** Test if flush list mutex is owned. */
irana's avatar
irana committed
1874
#define buf_flush_list_mutex_own(b) mutex_own(&b->flush_list_mutex)
inaam's avatar
inaam committed
1875 1876

/** Acquire the flush list mutex. */
irana's avatar
irana committed
1877 1878
#define buf_flush_list_mutex_enter(b) do {	\
	mutex_enter(&b->flush_list_mutex);	\
inaam's avatar
inaam committed
1879 1880
} while (0)
/** Release the flush list mutex. */
irana's avatar
irana committed
1881 1882
# define buf_flush_list_mutex_exit(b) do {	\
	mutex_exit(&b->flush_list_mutex);	\
inaam's avatar
inaam committed
1883 1884
} while (0)

irana's avatar
irana committed
1885 1886


1887
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1888
/** Forbid the release of the buffer pool mutex. */
irana's avatar
irana committed
1889 1890 1891
# define buf_pool_mutex_exit_forbid(b) do {	\
	ut_ad(buf_pool_mutex_own(b));		\
	b->mutex_exit_forbidden++;		\
1892
} while (0)
1893
/** Allow the release of the buffer pool mutex. */
irana's avatar
irana committed
1894 1895 1896 1897
# define buf_pool_mutex_exit_allow(b) do {	\
	ut_ad(buf_pool_mutex_own(b));		\
	ut_a(b->mutex_exit_forbidden);	\
	b->mutex_exit_forbidden--;		\
1898
} while (0)
1899
/** Release the buffer pool mutex. */
irana's avatar
irana committed
1900 1901 1902
# define buf_pool_mutex_exit(b) do {		\
	ut_a(!b->mutex_exit_forbidden);		\
	mutex_exit(&b->mutex);			\
1903 1904
} while (0)
#else
1905
/** Forbid the release of the buffer pool mutex. */
irana's avatar
irana committed
1906
# define buf_pool_mutex_exit_forbid(b) ((void) 0)
1907
/** Allow the release of the buffer pool mutex. */
irana's avatar
irana committed
1908
# define buf_pool_mutex_exit_allow(b) ((void) 0)
1909
/** Release the buffer pool mutex. */
irana's avatar
irana committed
1910
# define buf_pool_mutex_exit(b) mutex_exit(&b->mutex)
1911
#endif
1912
#endif /* !UNIV_HOTBACKUP */
1913
/* @} */
1914

1915
/**********************************************************************
osku's avatar
osku committed
1916 1917 1918 1919 1920 1921 1922 1923 1924 1925
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,
1926 1927
			pool: no_flush[flush_type] is in reset state,
			pool: n_flush[flush_type] > 0
1928

osku's avatar
osku committed
1929 1930 1931 1932 1933 1934 1935 1936
		(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
1937

osku's avatar
osku committed
1938 1939 1940 1941
		(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
1942
			if io_fix == BUF_IO_READ,
osku's avatar
osku committed
1943 1944 1945
				is x-locked
			if io_fix == BUF_IO_WRITE,
				is s-locked
1946

osku's avatar
osku committed
1947 1948 1949 1950 1951 1952
State transitions:

NOT_USED => READY_FOR_USE
READY_FOR_USE => MEMORY
READY_FOR_USE => FILE_PAGE
MEMORY => NOT_USED
1953
FILE_PAGE => NOT_USED	NOTE: This transition is allowed if and only if
osku's avatar
osku committed
1954 1955 1956
				(1) buf_fix_count == 0,
				(2) oldest_modification == 0, and
				(3) io_fix == 0.
1957
*/
osku's avatar
osku committed
1958 1959 1960 1961 1962 1963

#ifndef UNIV_NONINL
#include "buf0buf.ic"
#endif

#endif