84
84
The buffer buf_pool contains a single mutex which protects all the
85
85
control data structures of the buf_pool. The content of a buffer frame is
86
86
protected by a separate read-write lock in its control block, though.
87
These locks can be locked and unlocked without owning the buf_pool mutex.
87
These locks can be locked and unlocked without owning the buf_pool->mutex.
88
88
The OS events in the buf_pool struct can be waited for without owning the
91
The buf_pool mutex is a hot-spot in main memory, causing a lot of
91
The buf_pool->mutex is a hot-spot in main memory, causing a lot of
92
92
memory bus traffic on multiprocessor systems when processors
93
93
alternately access the mutex. On our Pentium, the mutex is accessed
94
94
maybe every 10 microseconds. We gave up the solution to have mutexes
95
95
for each control block, for instance, because it seemed to be
98
A solution to reduce mutex contention of the buf_pool mutex is to
98
A solution to reduce mutex contention of the buf_pool->mutex is to
99
99
create a separate mutex for the page hash table. On Pentium,
100
100
accessing the hash table takes 2 microseconds, about half
101
of the total buf_pool mutex hold time.
101
of the total buf_pool->mutex hold time.
153
153
which we can use when we want to artificially age a page in the
154
154
buf_pool. This is used if we know that some page is not needed
155
155
again for some time: we insert the block right after the pointer,
156
causing it to be replaced sooner than would noramlly be the case.
156
causing it to be replaced sooner than would normally be the case.
157
157
Currently this aging mechanism is used for read-ahead mechanism
158
158
of pages, and it can also be used when there is a scan of a full
159
159
table which cannot fit in the memory. Putting the pages near the
160
of the LRU list, we make sure that most of the buf_pool stays in the
161
main memory, undisturbed.
160
end of the LRU list, we make sure that most of the buf_pool stays
161
in the main memory, undisturbed.
163
163
The unzip_LRU list contains a subset of the common LRU list. The
164
164
blocks on the unzip_LRU list hold a compressed file page and the
246
247
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
248
249
/** The buffer buf_pool of the database */
249
UNIV_INTERN buf_pool_t* buf_pool = NULL;
251
/** mutex protecting the buffer pool struct and control blocks, except the
252
read-write lock in them */
253
UNIV_INTERN mutex_t buf_pool_mutex;
254
/** mutex protecting the control blocks of compressed-only pages
255
(of type buf_page_t, not buf_block_t) */
256
UNIV_INTERN mutex_t buf_pool_zip_mutex;
250
UNIV_INTERN buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS];
258
252
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
259
253
static ulint buf_dbg_counter = 0; /*!< This is used to insert validation
260
operations in excution in the
254
operations in execution in the
262
/** Flag to forbid the release of the buffer pool mutex.
263
Protected by buf_pool_mutex. */
264
UNIV_INTERN ulint buf_pool_mutex_exit_forbidden = 0;
265
256
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
266
257
#ifdef UNIV_DEBUG
267
258
/** If this is set TRUE, the program prints info whenever
269
260
UNIV_INTERN ibool buf_debug_prints = FALSE;
270
261
#endif /* UNIV_DEBUG */
263
#ifdef UNIV_PFS_RWLOCK
264
/* Keys to register buffer block related rwlocks and mutexes with
265
performance schema */
266
UNIV_INTERN mysql_pfs_key_t buf_block_lock_key;
267
# ifdef UNIV_SYNC_DEBUG
268
UNIV_INTERN mysql_pfs_key_t buf_block_debug_latch_key;
269
# endif /* UNIV_SYNC_DEBUG */
270
#endif /* UNIV_PFS_RWLOCK */
272
#ifdef UNIV_PFS_MUTEX
273
UNIV_INTERN mysql_pfs_key_t buffer_block_mutex_key;
274
UNIV_INTERN mysql_pfs_key_t buf_pool_mutex_key;
275
UNIV_INTERN mysql_pfs_key_t buf_pool_zip_mutex_key;
276
UNIV_INTERN mysql_pfs_key_t flush_list_mutex_key;
277
#endif /* UNIV_PFS_MUTEX */
279
#if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK
280
# ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
282
/* Buffer block mutexes and rwlocks can be registered
283
in one group rather than individually. If PFS_GROUP_BUFFER_SYNC
284
is defined, register buffer block mutex and rwlock
285
in one group after their initialization. */
286
# define PFS_GROUP_BUFFER_SYNC
288
/* This define caps the number of mutexes/rwlocks can
289
be registered with performance schema. Developers can
290
modify this define if necessary. Please note, this would
291
be effective only if PFS_GROUP_BUFFER_SYNC is defined. */
292
# define PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER ULINT_MAX
294
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
295
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
272
297
/** A chunk of buffers. The buffer pool is allocated in chunks. */
273
298
struct buf_chunk_struct{
274
299
ulint mem_size; /*!< allocated size of the chunk */
280
305
#endif /* !UNIV_HOTBACKUP */
282
307
/********************************************************************//**
308
Gets the smallest oldest_modification lsn for any page in the pool. Returns
309
zero if all modified pages have been flushed to disk.
310
@return oldest modification in pool, zero if none */
313
buf_pool_get_oldest_modification(void)
314
/*==================================*/
319
ib_uint64_t oldest_lsn = 0;
321
/* When we traverse all the flush lists we don't want another
322
thread to add a dirty page to any flush list. */
323
log_flush_order_mutex_enter();
325
for (i = 0; i < srv_buf_pool_instances; i++) {
326
buf_pool_t* buf_pool;
328
buf_pool = buf_pool_from_array(i);
330
buf_flush_list_mutex_enter(buf_pool);
332
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
335
ut_ad(bpage->in_flush_list);
336
lsn = bpage->oldest_modification;
339
buf_flush_list_mutex_exit(buf_pool);
341
if (!oldest_lsn || oldest_lsn > lsn) {
346
log_flush_order_mutex_exit();
348
/* The returned answer may be out of date: the flush_list can
349
change after the mutex has been released. */
354
/********************************************************************//**
355
Get total buffer pool statistics. */
358
buf_get_total_list_len(
359
/*===================*/
360
ulint* LRU_len, /*!< out: length of all LRU lists */
361
ulint* free_len, /*!< out: length of all free lists */
362
ulint* flush_list_len) /*!< out: length of all flush lists */
370
for (i = 0; i < srv_buf_pool_instances; i++) {
371
buf_pool_t* buf_pool;
373
buf_pool = buf_pool_from_array(i);
374
*LRU_len += UT_LIST_GET_LEN(buf_pool->LRU);
375
*free_len += UT_LIST_GET_LEN(buf_pool->free);
376
*flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
380
/********************************************************************//**
381
Get total buffer pool statistics. */
386
buf_pool_stat_t* tot_stat) /*!< out: buffer pool stats */
390
memset(tot_stat, 0, sizeof(*tot_stat));
392
for (i = 0; i < srv_buf_pool_instances; i++) {
393
buf_pool_stat_t*buf_stat;
394
buf_pool_t* buf_pool;
396
buf_pool = buf_pool_from_array(i);
398
buf_stat = &buf_pool->stat;
399
tot_stat->n_page_gets += buf_stat->n_page_gets;
400
tot_stat->n_pages_read += buf_stat->n_pages_read;
401
tot_stat->n_pages_written += buf_stat->n_pages_written;
402
tot_stat->n_pages_created += buf_stat->n_pages_created;
403
tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read;
404
tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted;
405
tot_stat->n_pages_made_young += buf_stat->n_pages_made_young;
407
tot_stat->n_pages_not_made_young +=
408
buf_stat->n_pages_not_made_young;
412
/********************************************************************//**
413
Allocates a buffer block.
414
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
419
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
420
ulint zip_size) /*!< in: compressed page size in bytes,
421
or 0 if uncompressed tablespace */
425
static ulint buf_pool_index;
427
if (buf_pool == NULL) {
428
/* We are allocating memory from any buffer pool, ensure
429
we spread the grace on all buffer pool instances. */
430
index = buf_pool_index++ % srv_buf_pool_instances;
431
buf_pool = buf_pool_from_array(index);
434
block = buf_LRU_get_free_block(buf_pool, zip_size);
436
buf_block_set_state(block, BUF_BLOCK_MEMORY);
441
/********************************************************************//**
283
442
Calculates a page checksum which is stored to the page when it is written
284
443
to a file. Note that we must be careful to calculate the same value on
285
444
32-bit and 64-bit architectures.
640
799
#ifndef UNIV_HOTBACKUP
801
# ifdef PFS_GROUP_BUFFER_SYNC
802
/********************************************************************//**
803
This function registers mutexes and rwlocks in buffer blocks with
804
performance schema. If PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER is
805
defined to be a value less than chunk->size, then only mutexes
806
and rwlocks in the first PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER
807
blocks are registered. */
810
pfs_register_buffer_block(
811
/*======================*/
812
buf_chunk_t* chunk) /*!< in/out: chunk of buffers */
815
ulint num_to_register;
818
block = chunk->blocks;
820
num_to_register = ut_min(chunk->size,
821
PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER);
823
for (i = 0; i < num_to_register; i++) {
827
# ifdef UNIV_PFS_MUTEX
828
mutex = &block->mutex;
829
ut_a(!mutex->pfs_psi);
830
mutex->pfs_psi = (PSI_server)
831
? PSI_server->init_mutex(buffer_block_mutex_key, mutex)
833
# endif /* UNIV_PFS_MUTEX */
835
# ifdef UNIV_PFS_RWLOCK
836
rwlock = &block->lock;
837
ut_a(!rwlock->pfs_psi);
838
rwlock->pfs_psi = (PSI_server)
839
? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
841
# endif /* UNIV_PFS_RWLOCK */
845
# endif /* PFS_GROUP_BUFFER_SYNC */
641
847
/********************************************************************//**
642
848
Initializes a buffer control block when the buf_pool is created. */
647
buf_block_t* block, /*!< in: pointer to control block */
648
byte* frame) /*!< in: pointer to buffer frame */
853
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
854
buf_block_t* block, /*!< in: pointer to control block */
855
byte* frame) /*!< in: pointer to buffer frame */
650
857
UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
652
859
block->frame = frame;
861
block->page.buf_pool = buf_pool;
654
862
block->page.state = BUF_BLOCK_NOT_USED;
655
863
block->page.buf_fix_count = 0;
656
864
block->page.io_fix = BUF_IO_NONE;
677
885
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
678
886
page_zip_des_init(&block->page.zip);
680
mutex_create(&block->mutex, SYNC_BUF_BLOCK);
682
rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
888
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
889
/* If PFS_SKIP_BUFFER_MUTEX_RWLOCK is defined, skip registration
890
of buffer block mutex/rwlock with performance schema. If
891
PFS_GROUP_BUFFER_SYNC is defined, skip the registration
892
since buffer block mutex/rwlock will be registered later in
893
pfs_register_buffer_block() */
895
mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
896
rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
897
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
898
mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
899
rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
900
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
683
902
ut_ad(rw_lock_validate(&(block->lock)));
685
904
#ifdef UNIV_SYNC_DEBUG
686
rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
905
rw_lock_create(buf_block_debug_latch_key,
906
&block->debug_latch, SYNC_NO_ORDER_CHECK);
687
907
#endif /* UNIV_SYNC_DEBUG */
942
1164
/********************************************************************//**
943
Creates the buffer pool.
944
@return own: buf_pool object, NULL if not enough memory or error */
1165
Set buffer pool size variables after resizing it */
1168
buf_pool_set_sizes(void)
1169
/*====================*/
1172
ulint curr_size = 0;
1174
buf_pool_mutex_enter_all();
1176
for (i = 0; i < srv_buf_pool_instances; i++) {
1177
buf_pool_t* buf_pool;
1179
buf_pool = buf_pool_from_array(i);
1180
curr_size += buf_pool->curr_pool_size;
1183
srv_buf_pool_curr_size = curr_size;
1184
srv_buf_pool_old_size = srv_buf_pool_size;
1186
buf_pool_mutex_exit_all();
1189
/********************************************************************//**
1190
Initialize a buffer pool instance.
1191
@return DB_SUCCESS if all goes well. */
1194
buf_pool_init_instance(
1195
/*===================*/
1196
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
1197
ulint buf_pool_size, /*!< in: size in bytes */
1198
ulint instance_no) /*!< in: id of the instance */
950
1201
buf_chunk_t* chunk;
953
buf_pool = mem_zalloc(sizeof(buf_pool_t));
955
1203
/* 1. Initialize general fields
956
1204
------------------------------- */
957
mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
958
mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
960
buf_pool_mutex_enter();
962
buf_pool->n_chunks = 1;
963
buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
965
UT_LIST_INIT(buf_pool->free);
967
if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
1205
mutex_create(buf_pool_mutex_key,
1206
&buf_pool->mutex, SYNC_BUF_POOL);
1207
mutex_create(buf_pool_zip_mutex_key,
1208
&buf_pool->zip_mutex, SYNC_BUF_BLOCK);
1210
buf_pool_mutex_enter(buf_pool);
1212
if (buf_pool_size > 0) {
1213
buf_pool->n_chunks = 1;
1214
buf_pool->chunks = chunk = mem_zalloc(sizeof *chunk);
1216
UT_LIST_INIT(buf_pool->free);
1218
if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
1222
buf_pool_mutex_exit(buf_pool);
1227
buf_pool->instance_no = instance_no;
1228
buf_pool->old_pool_size = buf_pool_size;
1229
buf_pool->curr_size = chunk->size;
1230
buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1232
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
1233
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
1235
buf_pool->last_printout_time = ut_time();
974
srv_buf_pool_old_size = srv_buf_pool_size;
975
buf_pool->curr_size = chunk->size;
976
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
978
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
979
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
981
buf_pool->last_printout_time = time(NULL);
983
1237
/* 2. Initialize flushing fields
984
1238
-------------------------------- */
1240
mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1241
SYNC_BUF_FLUSH_LIST);
986
1243
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
987
1244
buf_pool->no_flush[i] = os_event_create(NULL);
990
1247
/* 3. Initialize LRU fields
991
1248
--------------------------- */
992
/* All fields are initialized by mem_zalloc(). */
994
buf_pool_mutex_exit();
996
btr_search_sys_create(buf_pool->curr_size
997
* UNIV_PAGE_SIZE / sizeof(void*) / 64);
999
/* 4. Initialize the buddy allocator fields */
1000
/* All fields are initialized by mem_zalloc(). */
1250
/* All fields are initialized by mem_zalloc(). */
1252
buf_pool_mutex_exit(buf_pool);
1005
1257
/********************************************************************//**
1006
Frees the buffer pool at shutdown. This must not be invoked before
1007
freeing all mutexes. */
1258
free one buffer pool instance */
1261
buf_pool_free_instance(
1262
/*===================*/
1263
buf_pool_t* buf_pool) /* in,own: buffer pool instance
1013
1266
buf_chunk_t* chunk;
1014
1267
buf_chunk_t* chunks;
1032
1285
/********************************************************************//**
1286
Creates the buffer pool.
1287
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
1292
ulint total_size, /*!< in: size of the total pool in bytes */
1293
ulint n_instances) /*!< in: number of instances */
1297
/* We create an extra buffer pool instance, this instance is used
1298
for flushing the flush lists, to keep track of n_flush for all
1299
the buffer pools and also used as a waiting object during flushing. */
1300
for (i = 0; i < n_instances; i++) {
1304
ptr = mem_zalloc(sizeof(*ptr));
1306
size = total_size / n_instances;
1308
buf_pool_ptr[i] = ptr;
1310
if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
1312
mem_free(buf_pool_ptr[i]);
1314
/* Free all the instances created so far. */
1321
buf_pool_set_sizes();
1322
buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
1324
btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
1329
/********************************************************************//**
1330
Frees the buffer pool at shutdown. This must not be invoked before
1331
freeing all mutexes. */
1336
ulint n_instances) /*!< in: numbere of instances to free */
1340
for (i = 0; i < n_instances; i++) {
1341
buf_pool_free_instance(buf_pool_from_array(i));
1342
buf_pool_ptr[i] = NULL;
1346
/********************************************************************//**
1347
Drops adaptive hash index for a buffer pool instance. */
1350
buf_pool_drop_hash_index_instance(
1351
/*==============================*/
1352
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
1353
ibool* released_search_latch) /*!< out: flag for signalling
1354
whether the search latch was
1357
buf_chunk_t* chunks = buf_pool->chunks;
1358
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
1360
while (--chunk >= chunks) {
1362
buf_block_t* block = chunk->blocks;
1364
for (i = chunk->size; i--; block++) {
1365
/* block->is_hashed cannot be modified
1366
when we have an x-latch on btr_search_latch;
1367
see the comment in buf0buf.h */
1369
if (!block->is_hashed) {
1373
/* To follow the latching order, we
1374
have to release btr_search_latch
1375
before acquiring block->latch. */
1376
rw_lock_x_unlock(&btr_search_latch);
1377
/* When we release the search latch,
1378
we must rescan all blocks, because
1379
some may become hashed again. */
1380
*released_search_latch = TRUE;
1382
rw_lock_x_lock(&block->lock);
1384
/* This should be guaranteed by the
1385
callers, which will be holding
1386
btr_search_enabled_mutex. */
1387
ut_ad(!btr_search_enabled);
1389
/* Because we did not buffer-fix the
1390
block by calling buf_block_get_gen(),
1391
it is possible that the block has been
1392
allocated for some other use after
1393
btr_search_latch was released above.
1394
We do not care which file page the
1395
block is mapped to. All we want to do
1396
is to drop any hash entries referring
1399
/* It is possible that
1400
block->page.state != BUF_FILE_PAGE.
1401
Even that does not matter, because
1402
btr_search_drop_page_hash_index() will
1403
check block->is_hashed before doing
1404
anything. block->is_hashed can only
1405
be set on uncompressed file pages. */
1407
btr_search_drop_page_hash_index(block);
1409
rw_lock_x_unlock(&block->lock);
1411
rw_lock_x_lock(&btr_search_latch);
1413
ut_ad(!btr_search_enabled);
1418
/********************************************************************//**
1033
1419
Drops the adaptive hash index. To prevent a livelock, this function
1034
1420
is only to be called while holding btr_search_latch and while
1035
1421
btr_search_enabled == FALSE. */
1046
1432
ut_ad(!btr_search_enabled);
1049
buf_chunk_t* chunks = buf_pool->chunks;
1050
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
1052
1437
released_search_latch = FALSE;
1054
while (--chunk >= chunks) {
1055
buf_block_t* block = chunk->blocks;
1056
ulint i = chunk->size;
1058
for (; i--; block++) {
1059
/* block->is_hashed cannot be modified
1060
when we have an x-latch on btr_search_latch;
1061
see the comment in buf0buf.h */
1063
if (buf_block_get_state(block)
1064
!= BUF_BLOCK_FILE_PAGE
1065
|| !block->is_hashed) {
1069
/* To follow the latching order, we
1070
have to release btr_search_latch
1071
before acquiring block->latch. */
1072
rw_lock_x_unlock(&btr_search_latch);
1073
/* When we release the search latch,
1074
we must rescan all blocks, because
1075
some may become hashed again. */
1076
released_search_latch = TRUE;
1078
rw_lock_x_lock(&block->lock);
1080
/* This should be guaranteed by the
1081
callers, which will be holding
1082
btr_search_enabled_mutex. */
1083
ut_ad(!btr_search_enabled);
1085
/* Because we did not buffer-fix the
1086
block by calling buf_block_get_gen(),
1087
it is possible that the block has been
1088
allocated for some other use after
1089
btr_search_latch was released above.
1090
We do not care which file page the
1091
block is mapped to. All we want to do
1092
is to drop any hash entries referring
1095
/* It is possible that
1096
block->page.state != BUF_FILE_PAGE.
1097
Even that does not matter, because
1098
btr_search_drop_page_hash_index() will
1099
check block->is_hashed before doing
1100
anything. block->is_hashed can only
1101
be set on uncompressed file pages. */
1103
btr_search_drop_page_hash_index(block);
1105
rw_lock_x_unlock(&block->lock);
1107
rw_lock_x_lock(&btr_search_latch);
1109
ut_ad(!btr_search_enabled);
1439
for (i = 0; i < srv_buf_pool_instances; i++) {
1440
buf_pool_t* buf_pool;
1442
buf_pool = buf_pool_from_array(i);
1444
buf_pool_drop_hash_index_instance(
1445
buf_pool, &released_search_latch);
1112
1448
} while (released_search_latch);
1337
1677
goto shrink_again;
1341
srv_buf_pool_old_size = srv_buf_pool_size;
1682
buf_pool->old_pool_size = buf_pool->curr_pool_size;
1343
buf_pool_mutex_exit();
1684
buf_pool_mutex_exit(buf_pool);
1344
1685
btr_search_enable();
1347
1688
/********************************************************************//**
1348
Rebuild buf_pool->page_hash. */
1351
buf_pool_page_hash_rebuild(void)
1352
/*============================*/
1689
Shrinks the buffer pool. */
1694
ulint chunk_size) /*!< in: number of pages to remove */
1698
for (i = 0; i < srv_buf_pool_instances; i++) {
1699
buf_pool_t* buf_pool;
1700
ulint instance_chunk_size;
1702
instance_chunk_size = chunk_size / srv_buf_pool_instances;
1703
buf_pool = buf_pool_from_array(i);
1704
buf_pool_shrink_instance(buf_pool, instance_chunk_size);
1707
buf_pool_set_sizes();
1710
/********************************************************************//**
1711
Rebuild buf_pool->page_hash for a buffer pool instance. */
1714
buf_pool_page_hash_rebuild_instance(
1715
/*================================*/
1716
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
1355
1721
ulint n_chunks;
1722
hash_table_t* zip_hash;
1357
1723
hash_table_t* page_hash;
1358
hash_table_t* zip_hash;
1361
buf_pool_mutex_enter();
1725
buf_pool_mutex_enter(buf_pool);
1363
1727
/* Free, create, and populate the hash table. */
1364
1728
hash_table_free(buf_pool->page_hash);
1441
buf_pool_mutex_exit();
1806
buf_flush_list_mutex_exit(buf_pool);
1807
buf_pool_mutex_exit(buf_pool);
1810
/********************************************************************
1811
Determine if a block is a sentinel for a buffer pool watch.
1812
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
1815
buf_pool_watch_is_sentinel(
1816
/*=======================*/
1817
buf_pool_t* buf_pool, /*!< buffer pool instance */
1818
const buf_page_t* bpage) /*!< in: block */
1820
ut_ad(buf_page_in_file(bpage));
1822
if (bpage < &buf_pool->watch[0]
1823
|| bpage >= &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
1825
ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE
1826
|| bpage->zip.data != NULL);
1831
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
1832
ut_ad(!bpage->in_zip_hash);
1833
ut_ad(bpage->in_page_hash);
1834
ut_ad(bpage->zip.data == NULL);
1835
ut_ad(bpage->buf_fix_count > 0);
1839
/****************************************************************//**
1840
Add watch for the given page to be read in. Caller must have the buffer pool
1842
@return NULL if watch set, block if the page is in the buffer pool */
1847
ulint space, /*!< in: space id */
1848
ulint offset, /*!< in: page number */
1849
ulint fold) /*!< in: buf_page_address_fold(space, offset) */
1853
buf_pool_t* buf_pool = buf_pool_get(space, offset);
1855
ut_ad(buf_pool_mutex_own(buf_pool));
1857
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
1859
if (UNIV_LIKELY_NULL(bpage)) {
1860
if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
1861
/* The page was loaded meanwhile. */
1864
/* Add to an existing watch. */
1865
bpage->buf_fix_count++;
1869
for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
1870
bpage = &buf_pool->watch[i];
1872
ut_ad(bpage->access_time == 0);
1873
ut_ad(bpage->newest_modification == 0);
1874
ut_ad(bpage->oldest_modification == 0);
1875
ut_ad(bpage->zip.data == NULL);
1876
ut_ad(!bpage->in_zip_hash);
1878
switch (bpage->state) {
1879
case BUF_BLOCK_POOL_WATCH:
1880
ut_ad(!bpage->in_page_hash);
1881
ut_ad(bpage->buf_fix_count == 0);
1883
/* bpage is pointing to buf_pool_watch[],
1884
which is protected by buf_pool_mutex.
1885
Normally, buf_page_t objects are protected by
1886
buf_block_t::mutex or buf_pool->zip_mutex or both. */
1888
bpage->state = BUF_BLOCK_ZIP_PAGE;
1889
bpage->space = space;
1890
bpage->offset = offset;
1891
bpage->buf_fix_count = 1;
1893
ut_d(bpage->in_page_hash = TRUE);
1894
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
1897
case BUF_BLOCK_ZIP_PAGE:
1898
ut_ad(bpage->in_page_hash);
1899
ut_ad(bpage->buf_fix_count > 0);
1906
/* Allocation failed. Either the maximum number of purge
1907
threads should never exceed BUF_POOL_WATCH_SIZE, or this code
1908
should be modified to return a special non-NULL value and the
1909
caller should purge the record directly. */
1912
/* Fix compiler warning */
1916
/********************************************************************//**
1917
Rebuild buf_pool->page_hash. */
1920
buf_pool_page_hash_rebuild(void)
1921
/*============================*/
1925
for (i = 0; i < srv_buf_pool_instances; i++) {
1926
buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
1930
/********************************************************************//**
1931
Increase the buffer pool size of one buffer pool instance. */
1934
buf_pool_increase_instance(
1935
/*=======================*/
1936
buf_pool_t* buf_pool, /*!< in: buffer pool instane */
1937
ulint change_size) /*!< in: new size of the pool */
1939
buf_chunk_t* chunks;
1942
buf_pool_mutex_enter(buf_pool);
1943
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1945
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
1947
chunk = &chunks[buf_pool->n_chunks];
1949
if (!buf_chunk_init(buf_pool, chunk, change_size)) {
1952
buf_pool->old_pool_size = buf_pool->curr_pool_size;
1953
buf_pool->curr_size += chunk->size;
1954
buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1955
mem_free(buf_pool->chunks);
1956
buf_pool->chunks = chunks;
1957
buf_pool->n_chunks++;
1960
buf_pool_mutex_exit(buf_pool);
1963
/********************************************************************//**
1964
Increase the buffer pool size. */
1973
for (i = 0; i < srv_buf_pool_instances; i++) {
1974
buf_pool_increase_instance(
1975
buf_pool_from_array(i),
1976
change_size / srv_buf_pool_instances);
1979
buf_pool_set_sizes();
1444
1982
/********************************************************************//**
1448
1986
buf_pool_resize(void)
1449
1987
/*=================*/
1451
buf_pool_mutex_enter();
1453
if (srv_buf_pool_old_size == srv_buf_pool_size) {
1455
buf_pool_mutex_exit();
1990
ulint min_change_size = 1048576 * srv_buf_pool_instances;
1992
buf_pool_mutex_enter_all();
1994
if (srv_buf_pool_old_size == srv_buf_pool_size) {
1996
buf_pool_mutex_exit_all();
2000
} else if (srv_buf_pool_curr_size + min_change_size
2001
> srv_buf_pool_size) {
2003
change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
2006
buf_pool_mutex_exit_all();
2008
/* Disable adaptive hash indexes and empty the index
2009
in order to free up memory in the buffer pool chunks. */
2010
buf_pool_shrink(change_size);
2012
} else if (srv_buf_pool_curr_size + min_change_size
2013
< srv_buf_pool_size) {
2015
/* Enlarge the buffer pool by at least one megabyte */
2017
change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
2019
buf_pool_mutex_exit_all();
2021
buf_pool_increase(change_size);
2023
srv_buf_pool_size = srv_buf_pool_old_size;
2025
buf_pool_mutex_exit_all();
1459
if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
1461
buf_pool_mutex_exit();
1463
/* Disable adaptive hash indexes and empty the index
1464
in order to free up memory in the buffer pool chunks. */
1465
buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
1467
} else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
1469
/* Enlarge the buffer pool by at least one megabyte */
1472
= srv_buf_pool_size - srv_buf_pool_curr_size;
1473
buf_chunk_t* chunks;
1476
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1478
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
1481
chunk = &chunks[buf_pool->n_chunks];
1483
if (!buf_chunk_init(chunk, mem_size)) {
1486
buf_pool->curr_size += chunk->size;
1487
srv_buf_pool_curr_size = buf_pool->curr_size
1489
mem_free(buf_pool->chunks);
1490
buf_pool->chunks = chunks;
1491
buf_pool->n_chunks++;
2030
buf_pool_page_hash_rebuild();
2033
/****************************************************************//**
2034
Remove the sentinel block for the watch before replacing it with a real block.
2035
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
2036
the block has been replaced with the real block.
2037
@return reference count, to be added to the replacement block */
2040
buf_pool_watch_remove(
2041
/*==================*/
2042
buf_pool_t* buf_pool, /*!< buffer pool instance */
2043
ulint fold, /*!< in: buf_page_address_fold(
2045
buf_page_t* watch) /*!< in/out: sentinel for watch */
2047
ut_ad(buf_pool_mutex_own(buf_pool));
2049
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
2050
ut_d(watch->in_page_hash = FALSE);
2051
watch->buf_fix_count = 0;
2052
watch->state = BUF_BLOCK_POOL_WATCH;
2055
/****************************************************************//**
2056
Stop watching if the page has been read in.
2057
buf_pool_watch_set(space,offset) must have returned NULL before. */
2060
buf_pool_watch_unset(
2061
/*=================*/
2062
ulint space, /*!< in: space id */
2063
ulint offset) /*!< in: page number */
2066
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2067
ulint fold = buf_page_address_fold(space, offset);
2069
buf_pool_mutex_enter(buf_pool);
2070
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
2071
/* The page must exist because buf_pool_watch_set()
2072
increments buf_fix_count. */
2075
if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
2076
mutex_t* mutex = buf_page_get_mutex(bpage);
2079
ut_a(bpage->buf_fix_count > 0);
2080
bpage->buf_fix_count--;
2083
ut_a(bpage->buf_fix_count > 0);
2085
if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
2086
buf_pool_watch_remove(buf_pool, fold, bpage);
1494
srv_buf_pool_old_size = srv_buf_pool_size;
1495
buf_pool_mutex_exit();
1498
buf_pool_page_hash_rebuild();
2090
buf_pool_mutex_exit(buf_pool);
2093
/****************************************************************//**
2094
Check if the page has been read in.
2095
This may only be called after buf_pool_watch_set(space,offset)
2096
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
2097
@return FALSE if the given page was not read in, TRUE if it was */
2100
buf_pool_watch_occurred(
2101
/*====================*/
2102
ulint space, /*!< in: space id */
2103
ulint offset) /*!< in: page number */
2107
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2108
ulint fold = buf_page_address_fold(space, offset);
2110
buf_pool_mutex_enter(buf_pool);
2112
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
2113
/* The page must exist because buf_pool_watch_set()
2114
increments buf_fix_count. */
2116
ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
2117
buf_pool_mutex_exit(buf_pool);
1501
2122
/********************************************************************//**
1996
2661
/********************************************************************//**
2662
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
2663
the buf_block_t itself or a member of it
2664
@return TRUE if ptr belongs to a buf_block_t struct */
2667
buf_pointer_is_block_field(
2668
/*=======================*/
2669
const void* ptr) /*!< in: pointer not dereferenced */
2673
for (i = 0; i < srv_buf_pool_instances; i++) {
2676
found = buf_pointer_is_block_field_instance(
2677
buf_pool_from_array(i), ptr);
2686
/********************************************************************//**
1997
2687
Find out if a buffer block was created by buf_chunk_init().
1998
2688
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
2001
2691
buf_block_is_uncompressed(
2002
2692
/*======================*/
2003
const buf_block_t* block) /*!< in: pointer to block,
2693
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
2694
const buf_block_t* block) /*!< in: pointer to block,
2006
ut_ad(buf_pool_mutex_own());
2697
ut_ad(buf_pool_mutex_own(buf_pool));
2008
2699
if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2009
2700
/* The pointer should be aligned. */
2013
return(buf_pointer_is_block_field((void *)block));
2704
return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
2016
2707
/********************************************************************//**
2044
2738
|| (rw_latch == RW_X_LATCH)
2045
2739
|| (rw_latch == RW_NO_LATCH));
2046
2740
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
2047
ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
2048
|| (mode == BUF_GET_NO_LATCH));
2741
ut_ad(mode == BUF_GET
2742
|| mode == BUF_GET_IF_IN_POOL
2743
|| mode == BUF_GET_NO_LATCH
2744
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH);
2049
2745
ut_ad(zip_size == fil_space_get_zip_size(space));
2050
2746
ut_ad(ut_is_2pow(zip_size));
2051
2747
#ifndef UNIV_LOG_DEBUG
2052
2748
ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2054
2750
buf_pool->stat.n_page_gets++;
2751
fold = buf_page_address_fold(space, offset);
2057
buf_pool_mutex_enter();
2754
buf_pool_mutex_enter(buf_pool);
2060
2757
/* If the guess is a compressed page descriptor that
2144
2861
case BUF_BLOCK_ZIP_DIRTY:
2145
2862
bpage = &block->page;
2146
2863
/* Protect bpage->buf_fix_count. */
2147
mutex_enter(&buf_pool_zip_mutex);
2864
mutex_enter(&buf_pool->zip_mutex);
2149
2866
if (bpage->buf_fix_count
2150
2867
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2151
2868
/* This condition often occurs when the buffer
2152
2869
is not buffer-fixed, but I/O-fixed by
2153
2870
buf_page_init_for_read(). */
2154
mutex_exit(&buf_pool_zip_mutex);
2871
mutex_exit(&buf_pool->zip_mutex);
2155
2872
wait_until_unfixed:
2156
2873
/* The block is buffer-fixed or I/O-fixed.
2157
2874
Try again later. */
2158
buf_pool_mutex_exit();
2875
buf_pool_mutex_exit(buf_pool);
2159
2876
os_thread_sleep(WAIT_FOR_READ);
2164
2881
/* Allocate an uncompressed page. */
2165
buf_pool_mutex_exit();
2166
mutex_exit(&buf_pool_zip_mutex);
2882
buf_pool_mutex_exit(buf_pool);
2883
mutex_exit(&buf_pool->zip_mutex);
2168
block = buf_LRU_get_free_block(0);
2885
block = buf_LRU_get_free_block(buf_pool, 0);
2171
buf_pool_mutex_enter();
2888
buf_pool_mutex_enter(buf_pool);
2172
2889
mutex_enter(&block->mutex);
2175
buf_page_t* hash_bpage
2176
= buf_page_hash_get(space, offset);
2892
buf_page_t* hash_bpage;
2894
hash_bpage = buf_page_hash_get_low(
2895
buf_pool, space, offset, fold);
2178
2897
if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2179
2898
/* The buf_pool->page_hash was modified
2180
while buf_pool_mutex was released.
2899
while buf_pool->mutex was released.
2181
2900
Free the block that was allocated. */
2183
2902
buf_LRU_block_free_non_file_page(block);
2237
2956
block->page.buf_fix_count = 1;
2238
2957
buf_block_set_io_fix(block, BUF_IO_READ);
2239
rw_lock_x_lock_func(&block->lock, 0, file, line);
2958
rw_lock_x_lock(&block->lock);
2241
2960
UNIV_MEM_INVALID(bpage, sizeof *bpage);
2243
2962
mutex_exit(&block->mutex);
2244
mutex_exit(&buf_pool_zip_mutex);
2963
mutex_exit(&buf_pool->zip_mutex);
2245
2964
buf_pool->n_pend_unzip++;
2247
buf_buddy_free(bpage, sizeof *bpage);
2966
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
2249
buf_pool_mutex_exit();
2968
buf_pool_mutex_exit(buf_pool);
2251
2970
/* Decompress the page and apply buffered operations
2252
while not holding buf_pool_mutex or block->mutex. */
2971
while not holding buf_pool->mutex or block->mutex. */
2253
2972
success = buf_zip_decompress(block, srv_use_checksums);
2256
if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
2974
if (UNIV_LIKELY(success && !recv_no_ibuf_operations)) {
2257
2975
ibuf_merge_or_delete_for_page(block, space, offset,
2258
2976
zip_size, TRUE);
2261
2979
/* Unfix and unlatch the block. */
2262
buf_pool_mutex_enter();
2980
buf_pool_mutex_enter(buf_pool);
2263
2981
mutex_enter(&block->mutex);
2264
2982
block->page.buf_fix_count--;
2265
2983
buf_block_set_io_fix(block, BUF_IO_NONE);
2266
2984
mutex_exit(&block->mutex);
2267
2985
buf_pool->n_pend_unzip--;
2268
2986
rw_lock_x_unlock(&block->lock);
2988
if (UNIV_UNLIKELY(!success)) {
2990
buf_pool_mutex_exit(buf_pool);
2271
2996
case BUF_BLOCK_ZIP_FREE:
2716
3446
buf_block_init_low(block);
2718
block->lock_hash_val = lock_rec_hash(space, offset);
3448
block->lock_hash_val = lock_rec_hash(space, offset);
3450
buf_page_init_low(&block->page);
2720
3452
/* Insert into the hash table of file pages */
2722
hash_page = buf_page_hash_get(space, offset);
2724
if (UNIV_LIKELY_NULL(hash_page)) {
3454
hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
3456
if (UNIV_LIKELY(!hash_page)) {
3457
} else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
3458
/* Preserve the reference count. */
3459
ulint buf_fix_count = hash_page->buf_fix_count;
3461
ut_a(buf_fix_count > 0);
3462
block->page.buf_fix_count += buf_fix_count;
3463
buf_pool_watch_remove(buf_pool, fold, hash_page);
2725
3465
fprintf(stderr,
2726
3466
"InnoDB: Error: page %lu %lu already found"
2727
3467
" in the hash table: %p, %p\n",
2856
3606
if (UNIV_UNLIKELY(zip_size)) {
2857
3607
page_zip_set_size(&block->page.zip, zip_size);
2859
/* buf_pool_mutex may be released and
3609
/* buf_pool->mutex may be released and
2860
3610
reacquired by buf_buddy_alloc(). Thus, we
2861
3611
must release block->mutex in order not to
2862
3612
break the latching order in the reacquisition
2863
of buf_pool_mutex. We also must defer this
3613
of buf_pool->mutex. We also must defer this
2864
3614
operation until after the block descriptor has
2865
3615
been added to buf_pool->LRU and
2866
3616
buf_pool->page_hash. */
2867
3617
mutex_exit(&block->mutex);
2868
data = buf_buddy_alloc(zip_size, &lru);
3618
data = buf_buddy_alloc(buf_pool, zip_size, &lru);
2869
3619
mutex_enter(&block->mutex);
2870
3620
block->page.zip.data = data;
2889
3639
control block (bpage), in order to avoid the
2890
3640
invocation of buf_buddy_relocate_block() on
2891
3641
uninitialized data. */
2892
data = buf_buddy_alloc(zip_size, &lru);
2893
bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3642
data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3643
bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
3645
/* Initialize the buf_pool pointer. */
3646
bpage->buf_pool = buf_pool;
2895
3648
/* If buf_buddy_alloc() allocated storage from the LRU list,
2896
it released and reacquired buf_pool_mutex. Thus, we must
3649
it released and reacquired buf_pool->mutex. Thus, we must
2897
3650
check the page_hash again, as it may have been modified. */
2898
if (UNIV_UNLIKELY(lru)
2899
&& UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
2901
/* The block was added by some other thread. */
2902
buf_buddy_free(bpage, sizeof *bpage);
2903
buf_buddy_free(data, zip_size);
3651
if (UNIV_UNLIKELY(lru)) {
3653
watch_page = buf_page_hash_get_low(
3654
buf_pool, space, offset, fold);
3657
&& !buf_pool_watch_is_sentinel(buf_pool,
3660
/* The block was added by some other thread. */
3662
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
3663
buf_buddy_free(buf_pool, data, zip_size);
2909
3670
page_zip_des_init(&bpage->zip);
2910
3671
page_zip_set_size(&bpage->zip, zip_size);
2911
3672
bpage->zip.data = data;
2913
mutex_enter(&buf_pool_zip_mutex);
3674
mutex_enter(&buf_pool->zip_mutex);
2914
3675
UNIV_MEM_DESC(bpage->zip.data,
2915
3676
page_zip_get_size(&bpage->zip), bpage);
2916
3678
buf_page_init_low(bpage);
2917
3680
bpage->state = BUF_BLOCK_ZIP_PAGE;
2918
3681
bpage->space = space;
2919
3682
bpage->offset = offset;
2921
3685
#ifdef UNIV_DEBUG
2922
3686
bpage->in_page_hash = FALSE;
2923
3687
bpage->in_zip_hash = FALSE;
2927
3691
#endif /* UNIV_DEBUG */
2929
3693
ut_d(bpage->in_page_hash = TRUE);
2930
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2931
buf_page_address_fold(space, offset), bpage);
3695
if (UNIV_LIKELY_NULL(watch_page)) {
3696
/* Preserve the reference count. */
3697
ulint buf_fix_count = watch_page->buf_fix_count;
3698
ut_a(buf_fix_count > 0);
3699
bpage->buf_fix_count += buf_fix_count;
3700
ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
3701
buf_pool_watch_remove(buf_pool, fold, watch_page);
3704
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
2933
3707
/* The block must be put to the LRU list, to the old blocks */
2934
3708
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2971
3745
buf_frame_t* frame;
2972
3746
buf_block_t* block;
2973
3748
buf_block_t* free_block = NULL;
2974
3749
ulint time_ms = ut_time_ms();
3750
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2977
3753
ut_ad(mtr->state == MTR_ACTIVE);
2978
3754
ut_ad(space || !zip_size);
2980
free_block = buf_LRU_get_free_block(0);
2982
buf_pool_mutex_enter();
2984
block = (buf_block_t*) buf_page_hash_get(space, offset);
2986
if (block && buf_page_in_file(&block->page)) {
3756
free_block = buf_LRU_get_free_block(buf_pool, 0);
3758
fold = buf_page_address_fold(space, offset);
3760
buf_pool_mutex_enter(buf_pool);
3762
block = (buf_block_t*) buf_page_hash_get_low(
3763
buf_pool, space, offset, fold);
3766
&& buf_page_in_file(&block->page)
3767
&& !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2987
3768
#ifdef UNIV_IBUF_COUNT_DEBUG
2988
3769
ut_a(ibuf_count_get(space, offset) == 0);
3035
3816
page_zip_set_size(&block->page.zip, zip_size);
3036
3817
mutex_exit(&block->mutex);
3037
/* buf_pool_mutex may be released and reacquired by
3818
/* buf_pool->mutex may be released and reacquired by
3038
3819
buf_buddy_alloc(). Thus, we must release block->mutex
3039
3820
in order not to break the latching order in
3040
the reacquisition of buf_pool_mutex. We also must
3821
the reacquisition of buf_pool->mutex. We also must
3041
3822
defer this operation until after the block descriptor
3042
3823
has been added to buf_pool->LRU and buf_pool->page_hash. */
3043
data = buf_buddy_alloc(zip_size, &lru);
3824
data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3044
3825
mutex_enter(&block->mutex);
3045
3826
block->page.zip.data = data;
3305
4087
#endif /* UNIV_DEBUG */
3307
4089
mutex_exit(buf_page_get_mutex(bpage));
3308
buf_pool_mutex_exit();
3311
/*********************************************************************//**
3312
Invalidates the file pages in the buffer pool when an archive recovery is
3313
completed. All the file pages buffered must be in a replaceable state when
3314
this function is called: not latched and not modified. */
4090
buf_pool_mutex_exit(buf_pool);
4093
/*********************************************************************//**
4094
Asserts that all file pages in the buffer are in a replaceable state.
4098
buf_all_freed_instance(
4099
/*===================*/
4100
buf_pool_t* buf_pool) /*!< in: buffer pool instancce */
4107
buf_pool_mutex_enter(buf_pool);
4109
chunk = buf_pool->chunks;
4111
for (i = buf_pool->n_chunks; i--; chunk++) {
4113
const buf_block_t* block = buf_chunk_not_freed(chunk);
4115
if (UNIV_LIKELY_NULL(block)) {
4117
"Page %lu %lu still fixed or dirty\n",
4118
(ulong) block->page.space,
4119
(ulong) block->page.offset);
4124
buf_pool_mutex_exit(buf_pool);
4129
/*********************************************************************//**
4130
Invalidates file pages in one buffer pool instance */
3317
buf_pool_invalidate(void)
3318
/*=====================*/
4133
buf_pool_invalidate_instance(
4134
/*=========================*/
4135
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
3321
4138
enum buf_flush i;
3323
buf_pool_mutex_enter();
4140
buf_pool_mutex_enter(buf_pool);
3325
4142
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
3363
4180
buf_pool->LRU_flush_ended = 0;
3365
4182
memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
3366
buf_refresh_io_stats();
3368
buf_pool_mutex_exit();
4183
buf_refresh_io_stats(buf_pool);
4185
buf_pool_mutex_exit(buf_pool);
4188
/*********************************************************************//**
4189
Invalidates the file pages in the buffer pool when an archive recovery is
4190
completed. All the file pages buffered must be in a replaceable state when
4191
this function is called: not latched and not modified. */
4194
buf_pool_invalidate(void)
4195
/*=====================*/
4199
for (i = 0; i < srv_buf_pool_instances; i++) {
4200
buf_pool_invalidate_instance(buf_pool_from_array(i));
3371
4204
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3372
4205
/*********************************************************************//**
3373
Validates the buffer buf_pool data structure.
4206
Validates data in one buffer pool instance
3374
4207
@return TRUE */
4210
buf_pool_validate_instance(
4211
/*=======================*/
4212
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
3381
4215
buf_chunk_t* chunk;
4339
/* It is OK to read oldest_modification here because
4340
we have acquired buf_pool->zip_mutex above which acts
4341
as the 'block->mutex' for these bpages. */
3508
4342
ut_a(!b->oldest_modification);
3509
ut_a(buf_page_hash_get(b->space, b->offset) == b);
4343
ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3515
/* Check dirty compressed-only blocks. */
4349
/* Check dirty blocks. */
4351
buf_flush_list_mutex_enter(buf_pool);
3517
4352
for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
3518
4353
b = UT_LIST_GET_NEXT(list, b)) {
3519
4354
ut_ad(b->in_flush_list);
4355
ut_a(b->oldest_modification);
3521
4358
switch (buf_page_get_state(b)) {
3522
4359
case BUF_BLOCK_ZIP_DIRTY:
3523
ut_a(b->oldest_modification);
3527
4362
switch (buf_page_get_io_fix(b)) {
3528
4363
case BUF_IO_NONE:
3529
4364
case BUF_IO_READ:
3532
4366
case BUF_IO_WRITE:
3533
4367
switch (buf_page_get_flush_type(b)) {
3534
4368
case BUF_FLUSH_LRU:
3577
4415
(ulong) n_free);
3580
ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
3582
4419
ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
3583
4420
ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
3584
4421
ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
3586
buf_pool_mutex_exit();
4423
buf_pool_mutex_exit(buf_pool);
3588
4425
ut_a(buf_LRU_validate());
3589
ut_a(buf_flush_validate());
4426
ut_a(buf_flush_validate(buf_pool));
4431
/*********************************************************************//**
4432
Validates the buffer buf_pool data structure.
4441
for (i = 0; i < srv_buf_pool_instances; i++) {
4442
buf_pool_t* buf_pool;
4444
buf_pool = buf_pool_from_array(i);
4446
buf_pool_validate_instance(buf_pool);
3593
4451
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3595
4453
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3596
4454
/*********************************************************************//**
3597
Prints info of the buffer buf_pool data structure. */
4455
Prints info of the buffer buf_pool data structure for one instance. */
4460
buf_pool_t* buf_pool)
3603
4462
dulint* index_ids;
3947
4869
buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
3948
4870
buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
3950
buf_refresh_io_stats();
3951
buf_pool_mutex_exit();
4872
buf_refresh_io_stats(buf_pool);
4873
buf_pool_mutex_exit(buf_pool);
4876
/*********************************************************************//**
4877
Prints info of the buffer i/o. */
4882
FILE* file) /*!< in/out: buffer where to print */
4886
for (i = 0; i < srv_buf_pool_instances; i++) {
4887
buf_pool_t* buf_pool;
4889
buf_pool = buf_pool_from_array(i);
4890
buf_print_io_instance(buf_pool, file);
3954
4894
/**********************************************************************//**
3955
4895
Refreshes the statistics used to print per-second averages. */
3958
buf_refresh_io_stats(void)
3959
/*======================*/
4898
buf_refresh_io_stats(
4899
/*=================*/
4900
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
3961
buf_pool->last_printout_time = time(NULL);
4902
buf_pool->last_printout_time = ut_time();
3962
4903
buf_pool->old_stat = buf_pool->stat;
3965
/*********************************************************************//**
3966
Asserts that all file pages in the buffer are in a replaceable state.
4906
/**********************************************************************//**
4907
Refreshes the statistics used to print per-second averages. */
4910
buf_refresh_io_stats_all(void)
4911
/*==========================*/
4915
for (i = 0; i < srv_buf_pool_instances; i++) {
4916
buf_pool_t* buf_pool;
4918
buf_pool = buf_pool_from_array(i);
4920
buf_refresh_io_stats(buf_pool);
4924
/**********************************************************************//**
4925
Check if all pages in all buffer pools are in a replacable state.
4926
@return FALSE if not */
3970
4929
buf_all_freed(void)
3971
4930
/*===============*/
3978
buf_pool_mutex_enter();
3980
chunk = buf_pool->chunks;
3982
for (i = buf_pool->n_chunks; i--; chunk++) {
3984
const buf_block_t* block = buf_chunk_not_freed(chunk);
3986
if (UNIV_LIKELY_NULL(block)) {
3988
"Page %lu %lu still fixed or dirty\n",
3989
(ulong) block->page.space,
3990
(ulong) block->page.offset);
4934
for (i = 0; i < srv_buf_pool_instances; i++) {
4935
buf_pool_t* buf_pool;
4937
buf_pool = buf_pool_from_array(i);
4939
if (!buf_all_freed_instance(buf_pool)) {
3995
buf_pool_mutex_exit();
4000
4947
/*********************************************************************//**
4001
4948
Checks that there currently are no pending i/o-operations for the buffer
4006
4953
buf_pool_check_no_pending_io(void)
4007
4954
/*==============================*/
4011
buf_pool_mutex_enter();
4013
if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
4014
+ buf_pool->n_flush[BUF_FLUSH_LIST]
4015
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
4959
buf_pool_mutex_enter_all();
4961
for (i = 0; i < srv_buf_pool_instances && ret; i++) {
4962
const buf_pool_t* buf_pool;
4964
buf_pool = buf_pool_from_array(i);
4966
if (buf_pool->n_pend_reads
4967
+ buf_pool->n_flush[BUF_FLUSH_LRU]
4968
+ buf_pool->n_flush[BUF_FLUSH_LIST]
4969
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
4021
buf_pool_mutex_exit();
4975
buf_pool_mutex_exit_all();
4981
Code currently not used
4026
4982
/*********************************************************************//**
4027
4983
Gets the current length of the free list of buffer blocks.
4028
4984
@return length of the free list */