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 normally be the case.
156
causing it to be replaced sooner than would noramlly 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
end of the LRU list, we make sure that most of the buf_pool stays
161
in the main memory, undisturbed.
160
of the LRU list, we make sure that most of the buf_pool stays in the
161
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
243
242
#ifndef UNIV_HOTBACKUP
244
243
/** Value in microseconds */
245
244
static const int WAIT_FOR_READ = 5000;
246
/** Number of attemtps made to read in a page in the buffer pool */
247
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
249
246
/** The buffer buf_pool of the database */
250
UNIV_INTERN buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS];
247
UNIV_INTERN buf_pool_t* buf_pool = NULL;
249
/** mutex protecting the buffer pool struct and control blocks, except the
250
read-write lock in them */
251
UNIV_INTERN mutex_t buf_pool_mutex;
252
/** mutex protecting the control blocks of compressed-only pages
253
(of type buf_page_t, not buf_block_t) */
254
UNIV_INTERN mutex_t buf_pool_zip_mutex;
252
256
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
253
257
static ulint buf_dbg_counter = 0; /*!< This is used to insert validation
254
operations in execution in the
258
operations in excution in the
260
/** Flag to forbid the release of the buffer pool mutex.
261
Protected by buf_pool_mutex. */
262
UNIV_INTERN ulint buf_pool_mutex_exit_forbidden = 0;
256
263
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
257
264
#ifdef UNIV_DEBUG
258
265
/** If this is set TRUE, the program prints info whenever
260
267
UNIV_INTERN ibool buf_debug_prints = FALSE;
261
268
#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 */
297
270
/** A chunk of buffers. The buffer pool is allocated in chunks. */
298
271
struct buf_chunk_struct{
299
272
ulint mem_size; /*!< allocated size of the chunk */
305
278
#endif /* !UNIV_HOTBACKUP */
307
280
/********************************************************************//**
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
/********************************************************************//**
442
281
Calculates a page checksum which is stored to the page when it is written
443
282
to a file. Note that we must be careful to calculate the same value on
444
283
32-bit and 64-bit architectures.
799
638
#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 */
847
639
/********************************************************************//**
848
640
Initializes a buffer control block when the buf_pool is created. */
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 */
645
buf_block_t* block, /*!< in: pointer to control block */
646
byte* frame) /*!< in: pointer to buffer frame */
857
648
UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
859
650
block->frame = frame;
861
block->page.buf_pool = buf_pool;
862
652
block->page.state = BUF_BLOCK_NOT_USED;
863
653
block->page.buf_fix_count = 0;
864
654
block->page.io_fix = BUF_IO_NONE;
887
675
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
888
676
page_zip_des_init(&block->page.zip);
890
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
891
/* If PFS_SKIP_BUFFER_MUTEX_RWLOCK is defined, skip registration
892
of buffer block mutex/rwlock with performance schema. If
893
PFS_GROUP_BUFFER_SYNC is defined, skip the registration
894
since buffer block mutex/rwlock will be registered later in
895
pfs_register_buffer_block() */
897
mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
898
rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
899
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
900
mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
901
rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
902
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
678
mutex_create(&block->mutex, SYNC_BUF_BLOCK);
680
rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
904
681
ut_ad(rw_lock_validate(&(block->lock)));
906
683
#ifdef UNIV_SYNC_DEBUG
907
rw_lock_create(buf_block_debug_latch_key,
908
&block->debug_latch, SYNC_NO_ORDER_CHECK);
684
rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
909
685
#endif /* UNIV_SYNC_DEBUG */
1166
940
/********************************************************************//**
1167
Set buffer pool size variables after resizing it */
1170
buf_pool_set_sizes(void)
1171
/*====================*/
1174
ulint curr_size = 0;
1176
buf_pool_mutex_enter_all();
1178
for (i = 0; i < srv_buf_pool_instances; i++) {
1179
buf_pool_t* buf_pool;
1181
buf_pool = buf_pool_from_array(i);
1182
curr_size += buf_pool->curr_pool_size;
1185
srv_buf_pool_curr_size = curr_size;
1186
srv_buf_pool_old_size = srv_buf_pool_size;
1188
buf_pool_mutex_exit_all();
1191
/********************************************************************//**
1192
Initialize a buffer pool instance.
1193
@return DB_SUCCESS if all goes well. */
1196
buf_pool_init_instance(
1197
/*===================*/
1198
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
1199
ulint buf_pool_size, /*!< in: size in bytes */
1200
ulint instance_no) /*!< in: id of the instance */
941
Creates the buffer pool.
942
@return own: buf_pool object, NULL if not enough memory or error */
951
buf_pool = mem_zalloc(sizeof(buf_pool_t));
1205
953
/* 1. Initialize general fields
1206
954
------------------------------- */
1207
mutex_create(buf_pool_mutex_key,
1208
&buf_pool->mutex, SYNC_BUF_POOL);
1209
mutex_create(buf_pool_zip_mutex_key,
1210
&buf_pool->zip_mutex, SYNC_BUF_BLOCK);
1212
buf_pool_mutex_enter(buf_pool);
1214
if (buf_pool_size > 0) {
1215
buf_pool->n_chunks = 1;
1216
buf_pool->chunks = chunk = mem_zalloc(sizeof *chunk);
1218
UT_LIST_INIT(buf_pool->free);
1220
if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
1224
buf_pool_mutex_exit(buf_pool);
1229
buf_pool->instance_no = instance_no;
1230
buf_pool->old_pool_size = buf_pool_size;
1231
buf_pool->curr_size = chunk->size;
1232
buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1234
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
1235
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
1237
buf_pool->last_printout_time = ut_time();
955
mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
956
mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
958
buf_pool_mutex_enter();
960
buf_pool->n_chunks = 1;
961
buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
963
UT_LIST_INIT(buf_pool->free);
965
if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
972
srv_buf_pool_old_size = srv_buf_pool_size;
973
buf_pool->curr_size = chunk->size;
974
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
976
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
977
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
979
buf_pool->last_printout_time = time(NULL);
1239
981
/* 2. Initialize flushing fields
1240
982
-------------------------------- */
1242
mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1243
SYNC_BUF_FLUSH_LIST);
1245
984
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
1246
985
buf_pool->no_flush[i] = os_event_create(NULL);
1249
988
/* 3. Initialize LRU fields
1250
989
--------------------------- */
1252
/* All fields are initialized by mem_zalloc(). */
1254
buf_pool_mutex_exit(buf_pool);
990
/* All fields are initialized by mem_zalloc(). */
992
buf_pool_mutex_exit();
994
btr_search_sys_create(buf_pool->curr_size
995
* UNIV_PAGE_SIZE / sizeof(void*) / 64);
997
/* 4. Initialize the buddy allocator fields */
998
/* All fields are initialized by mem_zalloc(). */
1259
1003
/********************************************************************//**
1260
free one buffer pool instance */
1004
Frees the buffer pool at shutdown. This must not be invoked before
1005
freeing all mutexes. */
1263
buf_pool_free_instance(
1264
/*===================*/
1265
buf_pool_t* buf_pool) /* in,own: buffer pool instance
1268
1011
buf_chunk_t* chunk;
1269
1012
buf_chunk_t* chunks;
1287
1030
/********************************************************************//**
1288
Creates the buffer pool.
1289
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
1294
ulint total_size, /*!< in: size of the total pool in bytes */
1295
ulint n_instances) /*!< in: number of instances */
1299
/* We create an extra buffer pool instance, this instance is used
1300
for flushing the flush lists, to keep track of n_flush for all
1301
the buffer pools and also used as a waiting object during flushing. */
1302
for (i = 0; i < n_instances; i++) {
1306
ptr = mem_zalloc(sizeof(*ptr));
1308
size = total_size / n_instances;
1310
buf_pool_ptr[i] = ptr;
1312
if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
1314
mem_free(buf_pool_ptr[i]);
1316
/* Free all the instances created so far. */
1323
buf_pool_set_sizes();
1324
buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
1326
btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
1331
/********************************************************************//**
1332
Frees the buffer pool at shutdown. This must not be invoked before
1333
freeing all mutexes. */
1338
ulint n_instances) /*!< in: numbere of instances to free */
1342
for (i = 0; i < n_instances; i++) {
1343
buf_pool_free_instance(buf_pool_from_array(i));
1344
buf_pool_ptr[i] = NULL;
1348
/********************************************************************//**
1349
Drops adaptive hash index for a buffer pool instance. */
1352
buf_pool_drop_hash_index_instance(
1353
/*==============================*/
1354
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
1355
ibool* released_search_latch) /*!< out: flag for signalling
1356
whether the search latch was
1359
buf_chunk_t* chunks = buf_pool->chunks;
1360
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
1362
while (--chunk >= chunks) {
1364
buf_block_t* block = chunk->blocks;
1366
for (i = chunk->size; i--; block++) {
1367
/* block->is_hashed cannot be modified
1368
when we have an x-latch on btr_search_latch;
1369
see the comment in buf0buf.h */
1371
if (!block->is_hashed) {
1375
/* To follow the latching order, we
1376
have to release btr_search_latch
1377
before acquiring block->latch. */
1378
rw_lock_x_unlock(&btr_search_latch);
1379
/* When we release the search latch,
1380
we must rescan all blocks, because
1381
some may become hashed again. */
1382
*released_search_latch = TRUE;
1384
rw_lock_x_lock(&block->lock);
1386
/* This should be guaranteed by the
1387
callers, which will be holding
1388
btr_search_enabled_mutex. */
1389
ut_ad(!btr_search_enabled);
1391
/* Because we did not buffer-fix the
1392
block by calling buf_block_get_gen(),
1393
it is possible that the block has been
1394
allocated for some other use after
1395
btr_search_latch was released above.
1396
We do not care which file page the
1397
block is mapped to. All we want to do
1398
is to drop any hash entries referring
1401
/* It is possible that
1402
block->page.state != BUF_FILE_PAGE.
1403
Even that does not matter, because
1404
btr_search_drop_page_hash_index() will
1405
check block->is_hashed before doing
1406
anything. block->is_hashed can only
1407
be set on uncompressed file pages. */
1409
btr_search_drop_page_hash_index(block);
1411
rw_lock_x_unlock(&block->lock);
1413
rw_lock_x_lock(&btr_search_latch);
1415
ut_ad(!btr_search_enabled);
1420
/********************************************************************//**
1421
1031
Drops the adaptive hash index. To prevent a livelock, this function
1422
1032
is only to be called while holding btr_search_latch and while
1423
1033
btr_search_enabled == FALSE. */
1434
1044
ut_ad(!btr_search_enabled);
1047
buf_chunk_t* chunks = buf_pool->chunks;
1048
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
1439
1050
released_search_latch = FALSE;
1441
for (i = 0; i < srv_buf_pool_instances; i++) {
1442
buf_pool_t* buf_pool;
1444
buf_pool = buf_pool_from_array(i);
1446
buf_pool_drop_hash_index_instance(
1447
buf_pool, &released_search_latch);
1052
while (--chunk >= chunks) {
1053
buf_block_t* block = chunk->blocks;
1054
ulint i = chunk->size;
1056
for (; i--; block++) {
1057
/* block->is_hashed cannot be modified
1058
when we have an x-latch on btr_search_latch;
1059
see the comment in buf0buf.h */
1061
if (!block->is_hashed) {
1065
/* To follow the latching order, we
1066
have to release btr_search_latch
1067
before acquiring block->latch. */
1068
rw_lock_x_unlock(&btr_search_latch);
1069
/* When we release the search latch,
1070
we must rescan all blocks, because
1071
some may become hashed again. */
1072
released_search_latch = TRUE;
1074
rw_lock_x_lock(&block->lock);
1076
/* This should be guaranteed by the
1077
callers, which will be holding
1078
btr_search_enabled_mutex. */
1079
ut_ad(!btr_search_enabled);
1081
/* Because we did not buffer-fix the
1082
block by calling buf_block_get_gen(),
1083
it is possible that the block has been
1084
allocated for some other use after
1085
btr_search_latch was released above.
1086
We do not care which file page the
1087
block is mapped to. All we want to do
1088
is to drop any hash entries referring
1091
/* It is possible that
1092
block->page.state != BUF_FILE_PAGE.
1093
Even that does not matter, because
1094
btr_search_drop_page_hash_index() will
1095
check block->is_hashed before doing
1096
anything. block->is_hashed can only
1097
be set on uncompressed file pages. */
1099
btr_search_drop_page_hash_index(block);
1101
rw_lock_x_unlock(&block->lock);
1103
rw_lock_x_lock(&btr_search_latch);
1105
ut_ad(!btr_search_enabled);
1450
1108
} while (released_search_latch);
1679
1335
goto shrink_again;
1684
buf_pool->old_pool_size = buf_pool->curr_pool_size;
1339
srv_buf_pool_old_size = srv_buf_pool_size;
1686
buf_pool_mutex_exit(buf_pool);
1341
buf_pool_mutex_exit();
1687
1342
btr_search_enable();
1690
1345
/********************************************************************//**
1691
Shrinks the buffer pool. */
1696
ulint chunk_size) /*!< in: number of pages to remove */
1700
for (i = 0; i < srv_buf_pool_instances; i++) {
1701
buf_pool_t* buf_pool;
1702
ulint instance_chunk_size;
1704
instance_chunk_size = chunk_size / srv_buf_pool_instances;
1705
buf_pool = buf_pool_from_array(i);
1706
buf_pool_shrink_instance(buf_pool, instance_chunk_size);
1709
buf_pool_set_sizes();
1712
/********************************************************************//**
1713
Rebuild buf_pool->page_hash for a buffer pool instance. */
1716
buf_pool_page_hash_rebuild_instance(
1717
/*================================*/
1718
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
1346
Rebuild buf_pool->page_hash. */
1349
buf_pool_page_hash_rebuild(void)
1350
/*============================*/
1723
1353
ulint n_chunks;
1355
hash_table_t* page_hash;
1724
1356
hash_table_t* zip_hash;
1725
hash_table_t* page_hash;
1727
buf_pool_mutex_enter(buf_pool);
1359
buf_pool_mutex_enter();
1729
1361
/* Free, create, and populate the hash table. */
1730
1362
hash_table_free(buf_pool->page_hash);
1808
buf_flush_list_mutex_exit(buf_pool);
1809
buf_pool_mutex_exit(buf_pool);
1812
/********************************************************************
1813
Determine if a block is a sentinel for a buffer pool watch.
1814
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
1817
buf_pool_watch_is_sentinel(
1818
/*=======================*/
1819
buf_pool_t* buf_pool, /*!< buffer pool instance */
1820
const buf_page_t* bpage) /*!< in: block */
1822
ut_ad(buf_page_in_file(bpage));
1824
if (bpage < &buf_pool->watch[0]
1825
|| bpage >= &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
1827
ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE
1828
|| bpage->zip.data != NULL);
1833
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
1834
ut_ad(!bpage->in_zip_hash);
1835
ut_ad(bpage->in_page_hash);
1836
ut_ad(bpage->zip.data == NULL);
1837
ut_ad(bpage->buf_fix_count > 0);
1841
/****************************************************************//**
1842
Add watch for the given page to be read in. Caller must have the buffer pool
1844
@return NULL if watch set, block if the page is in the buffer pool */
1849
ulint space, /*!< in: space id */
1850
ulint offset, /*!< in: page number */
1851
ulint fold) /*!< in: buf_page_address_fold(space, offset) */
1855
buf_pool_t* buf_pool = buf_pool_get(space, offset);
1857
ut_ad(buf_pool_mutex_own(buf_pool));
1859
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
1861
if (UNIV_LIKELY_NULL(bpage)) {
1862
if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
1863
/* The page was loaded meanwhile. */
1866
/* Add to an existing watch. */
1867
bpage->buf_fix_count++;
1871
for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
1872
bpage = &buf_pool->watch[i];
1874
ut_ad(bpage->access_time == 0);
1875
ut_ad(bpage->newest_modification == 0);
1876
ut_ad(bpage->oldest_modification == 0);
1877
ut_ad(bpage->zip.data == NULL);
1878
ut_ad(!bpage->in_zip_hash);
1880
switch (bpage->state) {
1881
case BUF_BLOCK_POOL_WATCH:
1882
ut_ad(!bpage->in_page_hash);
1883
ut_ad(bpage->buf_fix_count == 0);
1885
/* bpage is pointing to buf_pool_watch[],
1886
which is protected by buf_pool_mutex.
1887
Normally, buf_page_t objects are protected by
1888
buf_block_t::mutex or buf_pool->zip_mutex or both. */
1890
bpage->state = BUF_BLOCK_ZIP_PAGE;
1891
bpage->space = space;
1892
bpage->offset = offset;
1893
bpage->buf_fix_count = 1;
1895
ut_d(bpage->in_page_hash = TRUE);
1896
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
1899
case BUF_BLOCK_ZIP_PAGE:
1900
ut_ad(bpage->in_page_hash);
1901
ut_ad(bpage->buf_fix_count > 0);
1908
/* Allocation failed. Either the maximum number of purge
1909
threads should never exceed BUF_POOL_WATCH_SIZE, or this code
1910
should be modified to return a special non-NULL value and the
1911
caller should purge the record directly. */
1914
/* Fix compiler warning */
1918
/********************************************************************//**
1919
Rebuild buf_pool->page_hash. */
1922
buf_pool_page_hash_rebuild(void)
1923
/*============================*/
1927
for (i = 0; i < srv_buf_pool_instances; i++) {
1928
buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
1932
/********************************************************************//**
1933
Increase the buffer pool size of one buffer pool instance. */
1936
buf_pool_increase_instance(
1937
/*=======================*/
1938
buf_pool_t* buf_pool, /*!< in: buffer pool instane */
1939
ulint change_size) /*!< in: new size of the pool */
1941
buf_chunk_t* chunks;
1944
buf_pool_mutex_enter(buf_pool);
1945
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1947
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
1949
chunk = &chunks[buf_pool->n_chunks];
1951
if (!buf_chunk_init(buf_pool, chunk, change_size)) {
1954
buf_pool->old_pool_size = buf_pool->curr_pool_size;
1955
buf_pool->curr_size += chunk->size;
1956
buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1957
mem_free(buf_pool->chunks);
1958
buf_pool->chunks = chunks;
1959
buf_pool->n_chunks++;
1962
buf_pool_mutex_exit(buf_pool);
1965
/********************************************************************//**
1966
Increase the buffer pool size. */
1975
for (i = 0; i < srv_buf_pool_instances; i++) {
1976
buf_pool_increase_instance(
1977
buf_pool_from_array(i),
1978
change_size / srv_buf_pool_instances);
1981
buf_pool_set_sizes();
1439
buf_pool_mutex_exit();
1984
1442
/********************************************************************//**
1988
1446
buf_pool_resize(void)
1989
1447
/*=================*/
1992
ulint min_change_size = 1048576 * srv_buf_pool_instances;
1994
buf_pool_mutex_enter_all();
1996
if (srv_buf_pool_old_size == srv_buf_pool_size) {
1998
buf_pool_mutex_exit_all();
2002
} else if (srv_buf_pool_curr_size + min_change_size
2003
> srv_buf_pool_size) {
2005
change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
2008
buf_pool_mutex_exit_all();
2010
/* Disable adaptive hash indexes and empty the index
2011
in order to free up memory in the buffer pool chunks. */
2012
buf_pool_shrink(change_size);
2014
} else if (srv_buf_pool_curr_size + min_change_size
2015
< srv_buf_pool_size) {
2017
/* Enlarge the buffer pool by at least one megabyte */
2019
change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
2021
buf_pool_mutex_exit_all();
2023
buf_pool_increase(change_size);
2025
srv_buf_pool_size = srv_buf_pool_old_size;
2027
buf_pool_mutex_exit_all();
1449
buf_pool_mutex_enter();
1451
if (srv_buf_pool_old_size == srv_buf_pool_size) {
1453
buf_pool_mutex_exit();
2032
buf_pool_page_hash_rebuild();
2035
/****************************************************************//**
2036
Remove the sentinel block for the watch before replacing it with a real block.
2037
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
2038
the block has been replaced with the real block.
2039
@return reference count, to be added to the replacement block */
2042
buf_pool_watch_remove(
2043
/*==================*/
2044
buf_pool_t* buf_pool, /*!< buffer pool instance */
2045
ulint fold, /*!< in: buf_page_address_fold(
2047
buf_page_t* watch) /*!< in/out: sentinel for watch */
2049
ut_ad(buf_pool_mutex_own(buf_pool));
2051
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
2052
ut_d(watch->in_page_hash = FALSE);
2053
watch->buf_fix_count = 0;
2054
watch->state = BUF_BLOCK_POOL_WATCH;
2057
/****************************************************************//**
2058
Stop watching if the page has been read in.
2059
buf_pool_watch_set(space,offset) must have returned NULL before. */
2062
buf_pool_watch_unset(
2063
/*=================*/
2064
ulint space, /*!< in: space id */
2065
ulint offset) /*!< in: page number */
2068
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2069
ulint fold = buf_page_address_fold(space, offset);
2071
buf_pool_mutex_enter(buf_pool);
2072
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
2073
/* The page must exist because buf_pool_watch_set()
2074
increments buf_fix_count. */
2077
if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
2078
mutex_t* mutex = buf_page_get_mutex(bpage);
2081
ut_a(bpage->buf_fix_count > 0);
2082
bpage->buf_fix_count--;
2085
ut_a(bpage->buf_fix_count > 0);
2087
if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
2088
buf_pool_watch_remove(buf_pool, fold, bpage);
1457
if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
1459
buf_pool_mutex_exit();
1461
/* Disable adaptive hash indexes and empty the index
1462
in order to free up memory in the buffer pool chunks. */
1463
buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
1465
} else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
1467
/* Enlarge the buffer pool by at least one megabyte */
1470
= srv_buf_pool_size - srv_buf_pool_curr_size;
1471
buf_chunk_t* chunks;
1474
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1476
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
1479
chunk = &chunks[buf_pool->n_chunks];
1481
if (!buf_chunk_init(chunk, mem_size)) {
1484
buf_pool->curr_size += chunk->size;
1485
srv_buf_pool_curr_size = buf_pool->curr_size
1487
mem_free(buf_pool->chunks);
1488
buf_pool->chunks = chunks;
1489
buf_pool->n_chunks++;
1492
srv_buf_pool_old_size = srv_buf_pool_size;
1493
buf_pool_mutex_exit();
2092
buf_pool_mutex_exit(buf_pool);
2095
/****************************************************************//**
2096
Check if the page has been read in.
2097
This may only be called after buf_pool_watch_set(space,offset)
2098
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
2099
@return FALSE if the given page was not read in, TRUE if it was */
2102
buf_pool_watch_occurred(
2103
/*====================*/
2104
ulint space, /*!< in: space id */
2105
ulint offset) /*!< in: page number */
2109
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2110
ulint fold = buf_page_address_fold(space, offset);
2112
buf_pool_mutex_enter(buf_pool);
2114
bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
2115
/* The page must exist because buf_pool_watch_set()
2116
increments buf_fix_count. */
2118
ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
2119
buf_pool_mutex_exit(buf_pool);
1496
buf_pool_page_hash_rebuild();
2124
1499
/********************************************************************//**
2663
1994
/********************************************************************//**
2664
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
2665
the buf_block_t itself or a member of it
2666
@return TRUE if ptr belongs to a buf_block_t struct */
2669
buf_pointer_is_block_field(
2670
/*=======================*/
2671
const void* ptr) /*!< in: pointer not dereferenced */
2675
for (i = 0; i < srv_buf_pool_instances; i++) {
2678
found = buf_pointer_is_block_field_instance(
2679
buf_pool_from_array(i), ptr);
2688
/********************************************************************//**
2689
1995
Find out if a buffer block was created by buf_chunk_init().
2690
1996
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
2693
1999
buf_block_is_uncompressed(
2694
2000
/*======================*/
2695
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
2696
const buf_block_t* block) /*!< in: pointer to block,
2001
const buf_block_t* block) /*!< in: pointer to block,
2699
ut_ad(buf_pool_mutex_own(buf_pool));
2004
ut_ad(buf_pool_mutex_own());
2701
2006
if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2702
2007
/* The pointer should be aligned. */
2706
return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
2011
return(buf_pointer_is_block_field((void *)block));
2709
2014
/********************************************************************//**
2720
2025
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2721
2026
buf_block_t* guess, /*!< in: guessed block or NULL */
2722
2027
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2723
BUF_GET_NO_LATCH, or
2724
BUF_GET_IF_IN_POOL_OR_WATCH */
2725
2029
const char* file, /*!< in: file name */
2726
2030
ulint line, /*!< in: line where called */
2727
2031
mtr_t* mtr) /*!< in: mini-transaction */
2729
2033
buf_block_t* block;
2731
2034
unsigned access_time;
2732
2035
ulint fix_type;
2733
2036
ibool must_read;
2735
buf_pool_t* buf_pool = buf_pool_get(space, offset);
2738
ut_ad(mtr->state == MTR_ACTIVE);
2739
2039
ut_ad((rw_latch == RW_S_LATCH)
2740
2040
|| (rw_latch == RW_X_LATCH)
2741
2041
|| (rw_latch == RW_NO_LATCH));
2742
2042
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
2743
ut_ad(mode == BUF_GET
2744
|| mode == BUF_GET_IF_IN_POOL
2745
|| mode == BUF_GET_NO_LATCH
2746
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH);
2043
ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
2044
|| (mode == BUF_GET_NO_LATCH));
2747
2045
ut_ad(zip_size == fil_space_get_zip_size(space));
2748
2046
ut_ad(ut_is_2pow(zip_size));
2749
2047
#ifndef UNIV_LOG_DEBUG
2750
2048
ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2752
2050
buf_pool->stat.n_page_gets++;
2753
fold = buf_page_address_fold(space, offset);
2756
buf_pool_mutex_enter(buf_pool);
2053
buf_pool_mutex_enter();
2759
2056
/* If the guess is a compressed page descriptor that
2779
2076
if (block == NULL) {
2780
block = (buf_block_t*) buf_page_hash_get_low(
2781
buf_pool, space, offset, fold);
2077
block = (buf_block_t*) buf_page_hash_get(space, offset);
2785
if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2789
2081
if (block == NULL) {
2790
2082
/* Page not in buf_pool: needs to be read from file */
2792
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2793
block = (buf_block_t*) buf_pool_watch_set(
2794
space, offset, fold);
2796
if (UNIV_LIKELY_NULL(block)) {
2802
buf_pool_mutex_exit(buf_pool);
2804
if (mode == BUF_GET_IF_IN_POOL
2805
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2084
buf_pool_mutex_exit();
2086
if (mode == BUF_GET_IF_IN_POOL) {
2810
if (buf_read_page(space, zip_size, offset)) {
2812
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
2815
fprintf(stderr, "InnoDB: Error: Unable"
2816
" to read tablespace %lu page no"
2817
" %lu into the buffer pool after"
2819
"InnoDB: The most probable cause"
2820
" of this error may be that the"
2821
" table has been corrupted.\n"
2822
"InnoDB: You can try to fix this"
2824
" innodb_force_recovery.\n"
2825
"InnoDB: Please see reference manual"
2826
" for more details.\n"
2827
"InnoDB: Aborting...\n",
2829
BUF_PAGE_READ_MAX_RETRIES);
2091
buf_read_page(space, zip_size, offset);
2834
2093
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2835
2094
ut_a(++buf_dbg_counter % 37 || buf_validate());
2863
2118
case BUF_BLOCK_ZIP_DIRTY:
2864
2119
bpage = &block->page;
2865
2120
/* Protect bpage->buf_fix_count. */
2866
mutex_enter(&buf_pool->zip_mutex);
2121
mutex_enter(&buf_pool_zip_mutex);
2868
2123
if (bpage->buf_fix_count
2869
2124
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2870
2125
/* This condition often occurs when the buffer
2871
2126
is not buffer-fixed, but I/O-fixed by
2872
2127
buf_page_init_for_read(). */
2873
mutex_exit(&buf_pool->zip_mutex);
2128
mutex_exit(&buf_pool_zip_mutex);
2874
2129
wait_until_unfixed:
2875
2130
/* The block is buffer-fixed or I/O-fixed.
2876
2131
Try again later. */
2877
buf_pool_mutex_exit(buf_pool);
2132
buf_pool_mutex_exit();
2878
2133
os_thread_sleep(WAIT_FOR_READ);
2883
2138
/* Allocate an uncompressed page. */
2884
buf_pool_mutex_exit(buf_pool);
2885
mutex_exit(&buf_pool->zip_mutex);
2139
buf_pool_mutex_exit();
2140
mutex_exit(&buf_pool_zip_mutex);
2887
block = buf_LRU_get_free_block(buf_pool, 0);
2142
block = buf_LRU_get_free_block(0);
2890
buf_pool_mutex_enter(buf_pool);
2145
buf_pool_mutex_enter();
2891
2146
mutex_enter(&block->mutex);
2894
buf_page_t* hash_bpage;
2896
hash_bpage = buf_page_hash_get_low(
2897
buf_pool, space, offset, fold);
2149
buf_page_t* hash_bpage
2150
= buf_page_hash_get(space, offset);
2899
2152
if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2900
2153
/* The buf_pool->page_hash was modified
2901
while buf_pool->mutex was released.
2154
while buf_pool_mutex was released.
2902
2155
Free the block that was allocated. */
2904
2157
buf_LRU_block_free_non_file_page(block);
2958
2225
block->page.buf_fix_count = 1;
2959
2226
buf_block_set_io_fix(block, BUF_IO_READ);
2960
rw_lock_x_lock_func(&block->lock, 0, file, line);
2962
UNIV_MEM_INVALID(bpage, sizeof *bpage);
2227
rw_lock_x_lock(&block->lock);
2964
2228
mutex_exit(&block->mutex);
2965
mutex_exit(&buf_pool->zip_mutex);
2229
mutex_exit(&buf_pool_zip_mutex);
2966
2230
buf_pool->n_pend_unzip++;
2968
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
2232
buf_buddy_free(bpage, sizeof *bpage);
2970
buf_pool_mutex_exit(buf_pool);
2234
buf_pool_mutex_exit();
2972
2236
/* Decompress the page and apply buffered operations
2973
while not holding buf_pool->mutex or block->mutex. */
2237
while not holding buf_pool_mutex or block->mutex. */
2974
2238
success = buf_zip_decompress(block, srv_use_checksums);
2977
if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
2240
if (UNIV_LIKELY(success)) {
2978
2241
ibuf_merge_or_delete_for_page(block, space, offset,
2979
2242
zip_size, TRUE);
2982
2245
/* Unfix and unlatch the block. */
2983
buf_pool_mutex_enter(buf_pool);
2246
buf_pool_mutex_enter();
2984
2247
mutex_enter(&block->mutex);
2985
2248
block->page.buf_fix_count--;
2986
2249
buf_block_set_io_fix(block, BUF_IO_NONE);
3448
2696
buf_block_init_low(block);
3450
block->lock_hash_val = lock_rec_hash(space, offset);
3452
buf_page_init_low(&block->page);
2698
block->lock_hash_val = lock_rec_hash(space, offset);
3454
2700
/* Insert into the hash table of file pages */
3456
hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
3458
if (UNIV_LIKELY(!hash_page)) {
3459
} else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
3460
/* Preserve the reference count. */
3461
ulint buf_fix_count = hash_page->buf_fix_count;
3463
ut_a(buf_fix_count > 0);
3464
block->page.buf_fix_count += buf_fix_count;
3465
buf_pool_watch_remove(buf_pool, fold, hash_page);
2702
hash_page = buf_page_hash_get(space, offset);
2704
if (UNIV_LIKELY_NULL(hash_page)) {
3467
2705
fprintf(stderr,
3468
2706
"InnoDB: Error: page %lu %lu already found"
3469
2707
" in the hash table: %p, %p\n",
3608
2836
if (UNIV_UNLIKELY(zip_size)) {
3609
2837
page_zip_set_size(&block->page.zip, zip_size);
3611
/* buf_pool->mutex may be released and
2839
/* buf_pool_mutex may be released and
3612
2840
reacquired by buf_buddy_alloc(). Thus, we
3613
2841
must release block->mutex in order not to
3614
2842
break the latching order in the reacquisition
3615
of buf_pool->mutex. We also must defer this
2843
of buf_pool_mutex. We also must defer this
3616
2844
operation until after the block descriptor has
3617
2845
been added to buf_pool->LRU and
3618
2846
buf_pool->page_hash. */
3619
2847
mutex_exit(&block->mutex);
3620
data = buf_buddy_alloc(buf_pool, zip_size, &lru);
2848
data = buf_buddy_alloc(zip_size, &lru);
3621
2849
mutex_enter(&block->mutex);
3622
2850
block->page.zip.data = data;
3641
2869
control block (bpage), in order to avoid the
3642
2870
invocation of buf_buddy_relocate_block() on
3643
2871
uninitialized data. */
3644
data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3645
bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
3647
/* Initialize the buf_pool pointer. */
3648
bpage->buf_pool = buf_pool;
2872
data = buf_buddy_alloc(zip_size, &lru);
2873
bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3650
2875
/* If buf_buddy_alloc() allocated storage from the LRU list,
3651
it released and reacquired buf_pool->mutex. Thus, we must
2876
it released and reacquired buf_pool_mutex. Thus, we must
3652
2877
check the page_hash again, as it may have been modified. */
3653
if (UNIV_UNLIKELY(lru)) {
3655
watch_page = buf_page_hash_get_low(
3656
buf_pool, space, offset, fold);
3659
&& !buf_pool_watch_is_sentinel(buf_pool,
3662
/* The block was added by some other thread. */
3664
buf_buddy_free(buf_pool, bpage, sizeof *bpage);
3665
buf_buddy_free(buf_pool, data, zip_size);
2878
if (UNIV_UNLIKELY(lru)
2879
&& UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
2881
/* The block was added by some other thread. */
2882
buf_buddy_free(bpage, sizeof *bpage);
2883
buf_buddy_free(data, zip_size);
3672
2889
page_zip_des_init(&bpage->zip);
3673
2890
page_zip_set_size(&bpage->zip, zip_size);
3674
2891
bpage->zip.data = data;
3676
mutex_enter(&buf_pool->zip_mutex);
2893
mutex_enter(&buf_pool_zip_mutex);
3677
2894
UNIV_MEM_DESC(bpage->zip.data,
3678
2895
page_zip_get_size(&bpage->zip), bpage);
3680
2896
buf_page_init_low(bpage);
3682
2897
bpage->state = BUF_BLOCK_ZIP_PAGE;
3683
2898
bpage->space = space;
3684
2899
bpage->offset = offset;
3687
2901
#ifdef UNIV_DEBUG
3688
2902
bpage->in_page_hash = FALSE;
3689
2903
bpage->in_zip_hash = FALSE;
3693
2907
#endif /* UNIV_DEBUG */
3695
2909
ut_d(bpage->in_page_hash = TRUE);
3697
if (UNIV_LIKELY_NULL(watch_page)) {
3698
/* Preserve the reference count. */
3699
ulint buf_fix_count = watch_page->buf_fix_count;
3700
ut_a(buf_fix_count > 0);
3701
bpage->buf_fix_count += buf_fix_count;
3702
ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
3703
buf_pool_watch_remove(buf_pool, fold, watch_page);
3706
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
2910
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2911
buf_page_address_fold(space, offset), bpage);
3709
2913
/* The block must be put to the LRU list, to the old blocks */
3710
2914
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3747
2951
buf_frame_t* frame;
3748
2952
buf_block_t* block;
3750
2953
buf_block_t* free_block = NULL;
3751
2954
ulint time_ms = ut_time_ms();
3752
buf_pool_t* buf_pool = buf_pool_get(space, offset);
3755
ut_ad(mtr->state == MTR_ACTIVE);
3756
2957
ut_ad(space || !zip_size);
3758
free_block = buf_LRU_get_free_block(buf_pool, 0);
3760
fold = buf_page_address_fold(space, offset);
3762
buf_pool_mutex_enter(buf_pool);
3764
block = (buf_block_t*) buf_page_hash_get_low(
3765
buf_pool, space, offset, fold);
3768
&& buf_page_in_file(&block->page)
3769
&& !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2959
free_block = buf_LRU_get_free_block(0);
2961
buf_pool_mutex_enter();
2963
block = (buf_block_t*) buf_page_hash_get(space, offset);
2965
if (block && buf_page_in_file(&block->page)) {
3770
2966
#ifdef UNIV_IBUF_COUNT_DEBUG
3771
2967
ut_a(ibuf_count_get(space, offset) == 0);
3818
3014
page_zip_set_size(&block->page.zip, zip_size);
3819
3015
mutex_exit(&block->mutex);
3820
/* buf_pool->mutex may be released and reacquired by
3016
/* buf_pool_mutex may be released and reacquired by
3821
3017
buf_buddy_alloc(). Thus, we must release block->mutex
3822
3018
in order not to break the latching order in
3823
the reacquisition of buf_pool->mutex. We also must
3019
the reacquisition of buf_pool_mutex. We also must
3824
3020
defer this operation until after the block descriptor
3825
3021
has been added to buf_pool->LRU and buf_pool->page_hash. */
3826
data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3022
data = buf_buddy_alloc(zip_size, &lru);
3827
3023
mutex_enter(&block->mutex);
3828
3024
block->page.zip.data = data;
4089
3284
#endif /* UNIV_DEBUG */
4091
3286
mutex_exit(buf_page_get_mutex(bpage));
4092
buf_pool_mutex_exit(buf_pool);
4095
/*********************************************************************//**
4096
Asserts that all file pages in the buffer are in a replaceable state.
4100
buf_all_freed_instance(
4101
/*===================*/
4102
buf_pool_t* buf_pool) /*!< in: buffer pool instancce */
4109
buf_pool_mutex_enter(buf_pool);
4111
chunk = buf_pool->chunks;
4113
for (i = buf_pool->n_chunks; i--; chunk++) {
4115
const buf_block_t* block = buf_chunk_not_freed(chunk);
4117
if (UNIV_LIKELY_NULL(block)) {
4119
"Page %lu %lu still fixed or dirty\n",
4120
(ulong) block->page.space,
4121
(ulong) block->page.offset);
4126
buf_pool_mutex_exit(buf_pool);
4131
/*********************************************************************//**
4132
Invalidates file pages in one buffer pool instance */
3287
buf_pool_mutex_exit();
3290
/*********************************************************************//**
3291
Invalidates the file pages in the buffer pool when an archive recovery is
3292
completed. All the file pages buffered must be in a replaceable state when
3293
this function is called: not latched and not modified. */
4135
buf_pool_invalidate_instance(
4136
/*=========================*/
4137
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
3296
buf_pool_invalidate(void)
3297
/*=====================*/
4140
3300
enum buf_flush i;
4142
buf_pool_mutex_enter(buf_pool);
3302
buf_pool_mutex_enter();
4144
3304
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
4182
3342
buf_pool->LRU_flush_ended = 0;
4184
3344
memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
4185
buf_refresh_io_stats(buf_pool);
4187
buf_pool_mutex_exit(buf_pool);
4190
/*********************************************************************//**
4191
Invalidates the file pages in the buffer pool when an archive recovery is
4192
completed. All the file pages buffered must be in a replaceable state when
4193
this function is called: not latched and not modified. */
4196
buf_pool_invalidate(void)
4197
/*=====================*/
4201
for (i = 0; i < srv_buf_pool_instances; i++) {
4202
buf_pool_invalidate_instance(buf_pool_from_array(i));
3345
buf_refresh_io_stats();
3347
buf_pool_mutex_exit();
4206
3350
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4207
3351
/*********************************************************************//**
4208
Validates data in one buffer pool instance
3352
Validates the buffer buf_pool data structure.
4209
3353
@return TRUE */
4212
buf_pool_validate_instance(
4213
/*=======================*/
4214
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
4217
3360
buf_chunk_t* chunk;
4341
/* It is OK to read oldest_modification here because
4342
we have acquired buf_pool->zip_mutex above which acts
4343
as the 'block->mutex' for these bpages. */
4344
3487
ut_a(!b->oldest_modification);
4345
ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3488
ut_a(buf_page_hash_get(b->space, b->offset) == b);
4351
/* Check dirty blocks. */
3494
/* Check dirty compressed-only blocks. */
4353
buf_flush_list_mutex_enter(buf_pool);
4354
3496
for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4355
3497
b = UT_LIST_GET_NEXT(list, b)) {
4356
3498
ut_ad(b->in_flush_list);
4357
ut_a(b->oldest_modification);
4360
3500
switch (buf_page_get_state(b)) {
4361
3501
case BUF_BLOCK_ZIP_DIRTY:
3502
ut_a(b->oldest_modification);
4364
3506
switch (buf_page_get_io_fix(b)) {
4365
3507
case BUF_IO_NONE:
4366
3508
case BUF_IO_READ:
4368
3511
case BUF_IO_WRITE:
4369
3512
switch (buf_page_get_flush_type(b)) {
4370
3513
case BUF_FLUSH_LRU:
4417
3556
(ulong) n_free);
3559
ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4421
3561
ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
4422
3562
ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
4423
3563
ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
4425
buf_pool_mutex_exit(buf_pool);
3565
buf_pool_mutex_exit();
4427
3567
ut_a(buf_LRU_validate());
4428
ut_a(buf_flush_validate(buf_pool));
4433
/*********************************************************************//**
4434
Validates the buffer buf_pool data structure.
4443
for (i = 0; i < srv_buf_pool_instances; i++) {
4444
buf_pool_t* buf_pool;
4446
buf_pool = buf_pool_from_array(i);
4448
buf_pool_validate_instance(buf_pool);
3568
ut_a(buf_flush_validate());
4453
3572
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
4455
3574
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4456
3575
/*********************************************************************//**
4457
Prints info of the buffer buf_pool data structure for one instance. */
3576
Prints info of the buffer buf_pool data structure. */
4462
buf_pool_t* buf_pool)
4464
index_id_t* index_ids;
4471
3589
buf_chunk_t* chunk;
4472
3590
dict_index_t* index;
4870
3926
buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
4871
3927
buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
4873
buf_refresh_io_stats(buf_pool);
4874
buf_pool_mutex_exit(buf_pool);
4877
/*********************************************************************//**
4878
Prints info of the buffer i/o. */
4883
FILE* file) /*!< in/out: buffer where to print */
4887
for (i = 0; i < srv_buf_pool_instances; i++) {
4888
buf_pool_t* buf_pool;
4890
buf_pool = buf_pool_from_array(i);
4891
buf_print_io_instance(buf_pool, file);
3929
buf_refresh_io_stats();
3930
buf_pool_mutex_exit();
4895
3933
/**********************************************************************//**
4896
3934
Refreshes the statistics used to print per-second averages. */
4899
buf_refresh_io_stats(
4900
/*=================*/
4901
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
3937
buf_refresh_io_stats(void)
3938
/*======================*/
4903
buf_pool->last_printout_time = ut_time();
3940
buf_pool->last_printout_time = time(NULL);
4904
3941
buf_pool->old_stat = buf_pool->stat;
4907
/**********************************************************************//**
4908
Refreshes the statistics used to print per-second averages. */
4911
buf_refresh_io_stats_all(void)
4912
/*==========================*/
4916
for (i = 0; i < srv_buf_pool_instances; i++) {
4917
buf_pool_t* buf_pool;
4919
buf_pool = buf_pool_from_array(i);
4921
buf_refresh_io_stats(buf_pool);
4925
/**********************************************************************//**
4926
Check if all pages in all buffer pools are in a replacable state.
4927
@return FALSE if not */
3944
/*********************************************************************//**
3945
Asserts that all file pages in the buffer are in a replaceable state.
4930
3949
buf_all_freed(void)
4931
3950
/*===============*/
4935
for (i = 0; i < srv_buf_pool_instances; i++) {
4936
buf_pool_t* buf_pool;
4938
buf_pool = buf_pool_from_array(i);
4940
if (!buf_all_freed_instance(buf_pool)) {
3957
buf_pool_mutex_enter();
3959
chunk = buf_pool->chunks;
3961
for (i = buf_pool->n_chunks; i--; chunk++) {
3963
const buf_block_t* block = buf_chunk_not_freed(chunk);
3965
if (UNIV_LIKELY_NULL(block)) {
3967
"Page %lu %lu still fixed or dirty\n",
3968
(ulong) block->page.space,
3969
(ulong) block->page.offset);
3974
buf_pool_mutex_exit();
4948
3979
/*********************************************************************//**
4949
3980
Checks that there currently are no pending i/o-operations for the buffer
4954
3985
buf_pool_check_no_pending_io(void)
4955
3986
/*==============================*/
4960
buf_pool_mutex_enter_all();
4962
for (i = 0; i < srv_buf_pool_instances && ret; i++) {
4963
const buf_pool_t* buf_pool;
4965
buf_pool = buf_pool_from_array(i);
4967
if (buf_pool->n_pend_reads
4968
+ buf_pool->n_flush[BUF_FLUSH_LRU]
4969
+ buf_pool->n_flush[BUF_FLUSH_LIST]
4970
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
3990
buf_pool_mutex_enter();
3992
if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
3993
+ buf_pool->n_flush[BUF_FLUSH_LIST]
3994
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
4976
buf_pool_mutex_exit_all();
4000
buf_pool_mutex_exit();
4982
Code currently not used
4983
4005
/*********************************************************************//**
4984
4006
Gets the current length of the free list of buffer blocks.
4985
4007
@return length of the free list */