1
1
/*****************************************************************************
3
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
51
51
#include "srv0srv.h"
53
53
/** The number of blocks from the LRU_old pointer onward, including
54
the block pointed to, must be buf_pool->LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
54
the block pointed to, must be buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
55
55
of the whole LRU list length, except that the tolerance defined below
56
56
is allowed. Note that the tolerance must be small enough such that for
57
57
even the BUF_LRU_OLD_MIN_LEN long LRU list, the LRU_old pointer is not
97
97
#define BUF_LRU_IO_TO_UNZIP_FACTOR 50
99
99
/** Sampled values buf_LRU_stat_cur.
100
Not protected by any mutex. Updated by buf_LRU_stat_update(). */
100
Protected by buf_pool_mutex. Updated by buf_LRU_stat_update(). */
101
101
static buf_LRU_stat_t buf_LRU_stat_arr[BUF_LRU_STAT_N_INTERVAL];
103
102
/** Cursor to buf_LRU_stat_arr[] that is updated in a round-robin fashion. */
104
103
static ulint buf_LRU_stat_arr_ind;
108
107
UNIV_INTERN buf_LRU_stat_t buf_LRU_stat_cur;
110
109
/** Running sum of past values of buf_LRU_stat_cur.
111
Updated by buf_LRU_stat_update(). Not Protected by any mutex. */
110
Updated by buf_LRU_stat_update(). Protected by buf_pool_mutex. */
112
111
UNIV_INTERN buf_LRU_stat_t buf_LRU_stat_sum;
116
115
/** @name Heuristics for detecting index scan @{ */
116
/** Reserve this much/BUF_LRU_OLD_RATIO_DIV of the buffer pool for
117
"old" blocks. Protected by buf_pool_mutex. */
118
UNIV_INTERN uint buf_LRU_old_ratio;
117
119
/** Move blocks to "new" LRU list only if the first access was at
118
120
least this many milliseconds ago. Not protected by any mutex or latch. */
119
121
UNIV_INTERN uint buf_LRU_old_threshold_ms;
122
124
/******************************************************************//**
123
125
Takes a block out of the LRU list and page hash table.
124
126
If the block is compressed-only (BUF_BLOCK_ZIP_PAGE),
125
the object will be freed and buf_pool->zip_mutex will be released.
127
the object will be freed and buf_pool_zip_mutex will be released.
127
129
If a compressed page or a compressed-only block descriptor is freed,
128
130
other compressed pages or compressed-only block descriptors may be
153
155
@return TRUE if should use unzip_LRU */
156
buf_LRU_evict_from_unzip_LRU(
157
/*=========================*/
158
buf_pool_t* buf_pool)
158
buf_LRU_evict_from_unzip_LRU(void)
159
/*==============================*/
163
ut_ad(buf_pool_mutex_own(buf_pool));
164
ut_ad(buf_pool_mutex_own());
165
166
/* If the unzip_LRU list is empty, we can only use the LRU. */
166
167
if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) {
229
230
buf_LRU_drop_page_hash_for_tablespace(
230
231
/*==================================*/
231
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
232
ulint id) /*!< in: space id */
232
ulint id) /*!< in: space id */
234
234
buf_page_t* bpage;
247
page_arr = static_cast<unsigned long *>(ut_malloc(
248
sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE));
250
buf_pool_mutex_enter(buf_pool);
247
page_arr = ut_malloc(sizeof(ulint)
248
* BUF_LRU_DROP_SEARCH_HASH_SIZE);
249
buf_pool_mutex_enter();
285
284
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
289
/* Array full. We release the buf_pool->mutex to
287
/* Array full. We release the buf_pool_mutex to
290
288
obey the latching order. */
291
buf_pool_mutex_exit(buf_pool);
293
buf_LRU_drop_page_hash_batch(
294
id, zip_size, page_arr, num_entries);
289
buf_pool_mutex_exit();
291
buf_LRU_drop_page_hash_batch(id, zip_size, page_arr,
298
buf_pool_mutex_enter(buf_pool);
294
buf_pool_mutex_enter();
300
296
mutex_exit(block_mutex);
323
buf_pool_mutex_exit(buf_pool);
319
buf_pool_mutex_exit();
325
321
/* Drop any remaining batch of search hashed pages. */
326
322
buf_LRU_drop_page_hash_batch(id, zip_size, page_arr, num_entries);
330
326
/******************************************************************//**
331
Invalidates all pages belonging to a given tablespace inside a specific
332
buffer pool instance when we are deleting the data file(s) of that
327
Invalidates all pages belonging to a given tablespace when we are deleting
328
the data file(s) of that tablespace. */
336
buf_LRU_invalidate_tablespace_buf_pool_instance(
337
/*============================================*/
338
buf_pool_t* buf_pool, /*!< buffer pool instance */
339
ulint id) /*!< in: space id */
331
buf_LRU_invalidate_tablespace(
332
/*==========================*/
333
ulint id) /*!< in: space id */
341
335
buf_page_t* bpage;
338
/* Before we attempt to drop pages one by one we first
339
attempt to drop page hash index entries in batches to make
340
it more efficient. The batching attempt is a best effort
341
attempt and does not guarantee that all pages hash entries
342
will be dropped. We get rid of remaining page hash entries
344
buf_LRU_drop_page_hash_for_tablespace(id);
345
buf_pool_mutex_enter(buf_pool);
347
buf_pool_mutex_enter();
347
349
all_freed = TRUE;
357
359
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
359
361
/* bpage->space and bpage->io_fix are protected by
360
buf_pool->mutex and block_mutex. It is safe to check
361
them while holding buf_pool->mutex only. */
362
buf_pool_mutex and block_mutex. It is safe to check
363
them while holding buf_pool_mutex only. */
363
365
if (buf_page_get_space(bpage) != id) {
364
366
/* Skip this block, as it does not belong to
404
406
/* Descriptors of uncompressed
405
407
blocks will not be relocated,
406
408
because we are holding the
409
411
case BUF_BLOCK_ZIP_PAGE:
410
412
case BUF_BLOCK_ZIP_DIRTY:
416
418
buf_pool_zip_mutex, it is
417
419
not necessary to acquire
418
420
further mutexes. */
419
ut_ad(&buf_pool->zip_mutex
421
ut_ad(&buf_pool_zip_mutex
421
423
ut_ad(mutex_own(block_mutex));
422
424
prev_bpage_buf_fix = TRUE;
460
462
/* The block_mutex should have been
461
463
released by buf_LRU_block_remove_hashed_page()
462
464
when it returns BUF_BLOCK_ZIP_FREE. */
463
ut_ad(block_mutex == &buf_pool->zip_mutex);
465
ut_ad(block_mutex == &buf_pool_zip_mutex);
464
466
ut_ad(!mutex_own(block_mutex));
466
468
if (prev_bpage_buf_fix) {
499
/******************************************************************//**
500
Invalidates all pages belonging to a given tablespace when we are deleting
501
the data file(s) of that tablespace. */
504
buf_LRU_invalidate_tablespace(
505
/*==========================*/
506
ulint id) /*!< in: space id */
510
/* Before we attempt to drop pages one by one we first
511
attempt to drop page hash index entries in batches to make
512
it more efficient. The batching attempt is a best effort
513
attempt and does not guarantee that all pages hash entries
514
will be dropped. We get rid of remaining page hash entries
516
for (i = 0; i < srv_buf_pool_instances; i++) {
517
buf_pool_t* buf_pool;
519
buf_pool = buf_pool_from_array(i);
520
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
521
buf_LRU_invalidate_tablespace_buf_pool_instance(buf_pool, id);
525
501
/********************************************************************//**
526
502
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
531
507
buf_page_t* bpage) /*!< in: pointer to the block in question */
534
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
536
ut_ad(buf_pool_mutex_own(buf_pool));
511
ut_ad(buf_pool_mutex_own());
537
512
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
539
514
/* Find the first successor of bpage in the LRU list
564
539
buf_LRU_free_from_unzip_LRU_list(
565
540
/*=============================*/
566
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
567
ulint n_iterations) /*!< in: how many times this has
568
been called repeatedly without
569
result: a high value means that
570
we should search farther; we will
571
search n_iterations / 5 of the
572
unzip_LRU list, or nothing if
541
ulint n_iterations) /*!< in: how many times this has been called
542
repeatedly without result: a high value means
543
that we should search farther; we will search
544
n_iterations / 5 of the unzip_LRU list,
545
or nothing if n_iterations >= 5 */
575
547
buf_block_t* block;
578
ut_ad(buf_pool_mutex_own(buf_pool));
550
ut_ad(buf_pool_mutex_own());
580
552
/* Theoratically it should be much easier to find a victim
581
553
from unzip_LRU as we can choose even a dirty block (as we'll
638
610
buf_LRU_free_from_common_LRU_list(
639
611
/*==============================*/
640
buf_pool_t* buf_pool,
642
/*!< in: how many times this has been called
612
ulint n_iterations) /*!< in: how many times this has been called
643
613
repeatedly without result: a high value means
644
614
that we should search farther; if
645
615
n_iterations < 10, then we search
707
677
buf_LRU_search_and_free_block(
708
678
/*==========================*/
709
buf_pool_t* buf_pool,
710
/*!< in: buffer pool instance */
712
/*!< in: how many times this has been called
679
ulint n_iterations) /*!< in: how many times this has been called
713
680
repeatedly without result: a high value means
714
681
that we should search farther; if
715
682
n_iterations < 10, then we search
721
688
ibool freed = FALSE;
723
buf_pool_mutex_enter(buf_pool);
690
buf_pool_mutex_enter();
725
freed = buf_LRU_free_from_unzip_LRU_list(buf_pool, n_iterations);
692
freed = buf_LRU_free_from_unzip_LRU_list(n_iterations);
728
freed = buf_LRU_free_from_common_LRU_list(
729
buf_pool, n_iterations);
695
freed = buf_LRU_free_from_common_LRU_list(n_iterations);
753
buf_LRU_try_free_flushed_blocks(
754
/*============================*/
755
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
719
buf_LRU_try_free_flushed_blocks(void)
720
/*=================================*/
758
if (buf_pool == NULL) {
761
for (i = 0; i < srv_buf_pool_instances; i++) {
762
buf_pool = buf_pool_from_array(i);
763
buf_LRU_try_free_flushed_blocks(buf_pool);
766
buf_pool_mutex_enter(buf_pool);
768
while (buf_pool->LRU_flush_ended > 0) {
770
buf_pool_mutex_exit(buf_pool);
772
buf_LRU_search_and_free_block(buf_pool, 1);
774
buf_pool_mutex_enter(buf_pool);
777
buf_pool_mutex_exit(buf_pool);
722
buf_pool_mutex_enter();
724
while (buf_pool->LRU_flush_ended > 0) {
726
buf_pool_mutex_exit();
728
buf_LRU_search_and_free_block(1);
730
buf_pool_mutex_enter();
733
buf_pool_mutex_exit();
781
736
/******************************************************************//**
782
Returns TRUE if less than 25 % of the buffer pool in any instance is
783
available. This can be used in heuristics to prevent huge transactions
784
eating up the whole buffer pool for their locks.
737
Returns TRUE if less than 25 % of the buffer pool is available. This can be
738
used in heuristics to prevent huge transactions eating up the whole buffer
739
pool for their locks.
785
740
@return TRUE if less than 25 % of buffer pool left */
788
743
buf_LRU_buf_pool_running_out(void)
789
744
/*==============================*/
794
for (i = 0; i < srv_buf_pool_instances && !ret; i++) {
795
buf_pool_t* buf_pool;
797
buf_pool = buf_pool_from_array(i);
799
buf_pool_mutex_enter(buf_pool);
801
if (!recv_recovery_on
802
&& UT_LIST_GET_LEN(buf_pool->free)
803
+ UT_LIST_GET_LEN(buf_pool->LRU)
804
< buf_pool->curr_size / 4) {
809
buf_pool_mutex_exit(buf_pool);
748
buf_pool_mutex_enter();
750
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
751
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 4) {
756
buf_pool_mutex_exit();
818
764
@return a free control block, or NULL if the buf_block->free list is empty */
821
buf_LRU_get_free_only(
822
/*==================*/
823
buf_pool_t* buf_pool)
767
buf_LRU_get_free_only(void)
768
/*=======================*/
825
770
buf_block_t* block;
827
ut_ad(buf_pool_mutex_own(buf_pool));
772
ut_ad(buf_pool_mutex_own());
829
774
block = (buf_block_t*) UT_LIST_GET_FIRST(buf_pool->free);
833
777
ut_ad(block->page.in_free_list);
834
778
ut_d(block->page.in_free_list = FALSE);
835
779
ut_ad(!block->page.in_flush_list);
842
786
buf_block_set_state(block, BUF_BLOCK_READY_FOR_USE);
843
787
UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
845
ut_ad(buf_pool_from_block(block) == buf_pool);
847
789
mutex_exit(&block->mutex);
860
802
buf_LRU_get_free_block(
861
803
/*===================*/
862
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
863
ulint zip_size) /*!< in: compressed page size in bytes,
864
or 0 if uncompressed tablespace */
804
ulint zip_size) /*!< in: compressed page size in bytes,
805
or 0 if uncompressed tablespace */
866
807
buf_block_t* block = NULL;
869
810
ibool mon_value_was = FALSE;
870
811
ibool started_monitor = FALSE;
872
buf_pool_mutex_enter(buf_pool);
813
buf_pool_mutex_enter();
874
815
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
875
816
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->curr_size / 20) {
938
879
/* If there is a block in the free list, take it */
939
block = buf_LRU_get_free_only(buf_pool);
880
block = buf_LRU_get_free_only();
942
ut_ad(buf_pool_from_block(block) == buf_pool);
944
883
#ifdef UNIV_DEBUG
945
884
block->page.zip.m_start =
946
885
#endif /* UNIV_DEBUG */
951
890
if (UNIV_UNLIKELY(zip_size)) {
953
892
page_zip_set_size(&block->page.zip, zip_size);
955
block->page.zip.data = static_cast<unsigned char *>(buf_buddy_alloc(
956
buf_pool, zip_size, &lru));
893
block->page.zip.data = buf_buddy_alloc(zip_size, &lru);
958
894
UNIV_MEM_DESC(block->page.zip.data, zip_size, block);
960
896
page_zip_set_size(&block->page.zip, 0);
961
897
block->page.zip.data = NULL;
964
buf_pool_mutex_exit(buf_pool);
900
buf_pool_mutex_exit();
966
902
if (started_monitor) {
967
903
srv_print_innodb_monitor = mon_value_was;
973
909
/* If no block was in the free list, search from the end of the LRU
974
910
list and try to free a block there */
976
buf_pool_mutex_exit(buf_pool);
912
buf_pool_mutex_exit();
978
freed = buf_LRU_search_and_free_block(buf_pool, n_iterations);
914
freed = buf_LRU_search_and_free_block(n_iterations);
1018
954
/* No free block was found: try to flush the LRU list */
1020
buf_flush_free_margin(buf_pool);
956
buf_flush_free_margin();
1021
957
++srv_buf_pool_wait_free;
1023
959
os_aio_simulated_wake_handler_threads();
1025
buf_pool_mutex_enter(buf_pool);
961
buf_pool_mutex_enter();
1027
963
if (buf_pool->LRU_flush_ended > 0) {
1028
964
/* We have written pages in an LRU flush. To make the insert
1029
965
buffer more efficient, we try to move these pages to the free
1032
buf_pool_mutex_exit(buf_pool);
968
buf_pool_mutex_exit();
1034
buf_LRU_try_free_flushed_blocks(buf_pool);
970
buf_LRU_try_free_flushed_blocks();
1036
buf_pool_mutex_exit(buf_pool);
972
buf_pool_mutex_exit();
1039
975
if (n_iterations > 10) {
1051
987
is inside the allowed limits. */
1054
buf_LRU_old_adjust_len(
1055
/*===================*/
1056
buf_pool_t* buf_pool) /*!< in: buffer pool instance */
990
buf_LRU_old_adjust_len(void)
991
/*========================*/
1061
996
ut_a(buf_pool->LRU_old);
1062
ut_ad(buf_pool_mutex_own(buf_pool));
1063
ut_ad(buf_pool->LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN);
1064
ut_ad(buf_pool->LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX);
997
ut_ad(buf_pool_mutex_own());
998
ut_ad(buf_LRU_old_ratio >= BUF_LRU_OLD_RATIO_MIN);
999
ut_ad(buf_LRU_old_ratio <= BUF_LRU_OLD_RATIO_MAX);
1065
1000
#if BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)
1066
1001
# error "BUF_LRU_OLD_RATIO_MIN * BUF_LRU_OLD_MIN_LEN <= BUF_LRU_OLD_RATIO_DIV * (BUF_LRU_OLD_TOLERANCE + 5)"
1078
1013
old_len = buf_pool->LRU_old_len;
1079
1014
new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU)
1080
* buf_pool->LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV,
1015
* buf_LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV,
1081
1016
UT_LIST_GET_LEN(buf_pool->LRU)
1082
1017
- (BUF_LRU_OLD_TOLERANCE
1083
1018
+ BUF_LRU_NON_OLD_MIN_LEN));
1119
1054
called when the LRU list grows to BUF_LRU_OLD_MIN_LEN length. */
1124
buf_pool_t* buf_pool)
1057
buf_LRU_old_init(void)
1058
/*==================*/
1126
1060
buf_page_t* bpage;
1128
ut_ad(buf_pool_mutex_own(buf_pool));
1062
ut_ad(buf_pool_mutex_own());
1129
1063
ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN);
1131
1065
/* We first initialize all blocks in the LRU list as old and then use
1144
1078
buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
1145
1079
buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU);
1147
buf_LRU_old_adjust_len(buf_pool);
1081
buf_LRU_old_adjust_len();
1150
1084
/******************************************************************//**
1155
1089
/*=================================*/
1156
1090
buf_page_t* bpage) /*!< in/out: control block */
1158
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
1160
1092
ut_ad(buf_pool);
1162
1094
ut_ad(buf_page_in_file(bpage));
1163
ut_ad(buf_pool_mutex_own(buf_pool));
1095
ut_ad(buf_pool_mutex_own());
1165
1097
if (buf_page_belongs_to_unzip_LRU(bpage)) {
1166
1098
buf_block_t* block = (buf_block_t*) bpage;
1180
1112
/*=================*/
1181
1113
buf_page_t* bpage) /*!< in: control block */
1183
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
1185
1115
ut_ad(buf_pool);
1187
ut_ad(buf_pool_mutex_own(buf_pool));
1117
ut_ad(buf_pool_mutex_own());
1189
1119
ut_a(buf_page_in_file(bpage));
1198
1128
/* Below: the previous block is guaranteed to exist,
1199
1129
because the LRU_old pointer is only allowed to differ
1200
1130
by BUF_LRU_OLD_TOLERANCE from strict
1201
buf_pool->LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV of the LRU
1131
buf_LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV of the LRU
1202
1132
list length. */
1203
1133
buf_page_t* prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
1257
1187
ibool old) /*!< in: TRUE if should be put to the end
1258
1188
of the list, else put to the start */
1260
buf_pool_t* buf_pool = buf_pool_from_block(block);
1262
1190
ut_ad(buf_pool);
1264
ut_ad(buf_pool_mutex_own(buf_pool));
1192
ut_ad(buf_pool_mutex_own());
1266
1194
ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
1283
1211
/*=========================*/
1284
1212
buf_page_t* bpage) /*!< in: control block */
1286
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
1288
1214
ut_ad(buf_pool);
1290
ut_ad(buf_pool_mutex_own(buf_pool));
1216
ut_ad(buf_pool_mutex_own());
1292
1218
ut_a(buf_page_in_file(bpage));
1304
1230
buf_page_set_old(bpage, TRUE);
1305
1231
buf_pool->LRU_old_len++;
1306
buf_LRU_old_adjust_len(buf_pool);
1232
buf_LRU_old_adjust_len();
1308
1234
} else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
1310
1236
/* The LRU list is now long enough for LRU_old to become
1311
1237
defined: init it */
1313
buf_LRU_old_init(buf_pool);
1315
1241
buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
1334
1260
LRU list is very short, the block is added to
1335
1261
the start, regardless of this parameter */
1337
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
1339
1263
ut_ad(buf_pool);
1341
ut_ad(buf_pool_mutex_own(buf_pool));
1265
ut_ad(buf_pool_mutex_own());
1343
1267
ut_a(buf_page_in_file(bpage));
1344
1268
ut_ad(!bpage->in_LRU_list);
1372
1296
/* Adjust the length of the old block list if necessary */
1374
1298
buf_page_set_old(bpage, old);
1375
buf_LRU_old_adjust_len(buf_pool);
1299
buf_LRU_old_adjust_len();
1377
1301
} else if (UT_LIST_GET_LEN(buf_pool->LRU) == BUF_LRU_OLD_MIN_LEN) {
1379
1303
/* The LRU list is now long enough for LRU_old to become
1380
1304
defined: init it */
1382
buf_LRU_old_init(buf_pool);
1384
1308
buf_page_set_old(bpage, buf_pool->LRU_old != NULL);
1415
1339
/*=====================*/
1416
1340
buf_page_t* bpage) /*!< in: control block */
1418
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
1420
ut_ad(buf_pool_mutex_own(buf_pool));
1342
ut_ad(buf_pool_mutex_own());
1422
1344
if (bpage->old) {
1423
1345
buf_pool->stat.n_pages_made_young++;
1444
1366
page, the descriptor object will be freed as well.
1446
1368
NOTE: If this function returns BUF_LRU_FREED, it will temporarily
1447
release buf_pool->mutex. Furthermore, the page frame will no longer be
1369
release buf_pool_mutex. Furthermore, the page frame will no longer be
1448
1370
accessible via bpage.
1450
The caller must hold buf_pool->mutex and buf_page_get_mutex(bpage) and
1372
The caller must hold buf_pool_mutex and buf_page_get_mutex(bpage) and
1451
1373
release these two mutexes after the call. No other
1452
1374
buf_page_get_mutex() may be held when calling this function.
1453
1375
@return BUF_LRU_FREED if freed, BUF_LRU_CANNOT_RELOCATE or
1465
1387
was temporarily released, or NULL */
1467
1389
buf_page_t* b = NULL;
1468
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
1469
1390
mutex_t* block_mutex = buf_page_get_mutex(bpage);
1471
ut_ad(buf_pool_mutex_own(buf_pool));
1392
ut_ad(buf_pool_mutex_own());
1472
1393
ut_ad(mutex_own(block_mutex));
1473
1394
ut_ad(buf_page_in_file(bpage));
1474
1395
ut_ad(bpage->in_LRU_list);
1512
1433
If it cannot be allocated (without freeing a block
1513
1434
from the LRU list), refuse to free bpage. */
1515
buf_pool_mutex_exit_forbid(buf_pool);
1516
b = static_cast<buf_page_t *>(buf_buddy_alloc(buf_pool, sizeof *b, NULL));
1517
buf_pool_mutex_exit_allow(buf_pool);
1436
buf_pool_mutex_exit_forbid();
1437
b = buf_buddy_alloc(sizeof *b, NULL);
1438
buf_pool_mutex_exit_allow();
1519
1440
if (UNIV_UNLIKELY(!b)) {
1520
1441
return(BUF_LRU_CANNOT_RELOCATE);
1536
1457
ut_a(bpage->buf_fix_count == 0);
1540
1460
buf_page_t* prev_b = UT_LIST_GET_PREV(LRU, b);
1542
const ulint fold = buf_page_address_fold(
1461
const ulint fold = buf_page_address_fold(
1543
1462
bpage->space, bpage->offset);
1545
hash_b = buf_page_hash_get_low(
1546
buf_pool, bpage->space, bpage->offset, fold);
1464
ut_a(!buf_page_hash_get(bpage->space, bpage->offset));
1550
1466
b->state = b->oldest_modification
1551
1467
? BUF_BLOCK_ZIP_DIRTY
1605
1521
ut_ad(buf_pool->LRU_old);
1606
1522
/* Adjust the length of the
1607
1523
old block list if necessary */
1608
buf_LRU_old_adjust_len(buf_pool);
1524
buf_LRU_old_adjust_len();
1609
1525
} else if (lru_len == BUF_LRU_OLD_MIN_LEN) {
1610
1526
/* The LRU list is now long
1611
1527
enough for LRU_old to become
1612
1528
defined: init it */
1613
buf_LRU_old_init(buf_pool);
1615
1531
#ifdef UNIV_LRU_DEBUG
1616
1532
/* Check that the "old" flag is consistent
1675
1591
: BUF_NO_CHECKSUM_MAGIC);
1678
buf_pool_mutex_enter(buf_pool);
1594
buf_pool_mutex_enter();
1679
1595
mutex_enter(block_mutex);
1682
mutex_enter(&buf_pool->zip_mutex);
1598
mutex_enter(&buf_pool_zip_mutex);
1683
1599
b->buf_fix_count--;
1684
1600
buf_page_set_io_fix(b, BUF_IO_NONE);
1685
mutex_exit(&buf_pool->zip_mutex);
1601
mutex_exit(&buf_pool_zip_mutex);
1688
1604
buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
1690
1606
/* The block_mutex should have been released by
1691
1607
buf_LRU_block_remove_hashed_page() when it returns
1692
1608
BUF_BLOCK_ZIP_FREE. */
1693
ut_ad(block_mutex == &buf_pool->zip_mutex);
1609
ut_ad(block_mutex == &buf_pool_zip_mutex);
1694
1610
mutex_enter(block_mutex);
1705
1621
/*=============================*/
1706
1622
buf_block_t* block) /*!< in: block, must not contain a file page */
1709
buf_pool_t* buf_pool = buf_pool_from_block(block);
1712
ut_ad(buf_pool_mutex_own(buf_pool));
1627
ut_ad(buf_pool_mutex_own());
1713
1628
ut_ad(mutex_own(&block->mutex));
1715
1630
switch (buf_block_get_state(block)) {
1744
1659
block->page.zip.data = NULL;
1745
1660
mutex_exit(&block->mutex);
1746
buf_pool_mutex_exit_forbid(buf_pool);
1749
buf_pool, data, page_zip_get_size(&block->page.zip));
1751
buf_pool_mutex_exit_allow(buf_pool);
1661
buf_pool_mutex_exit_forbid();
1662
buf_buddy_free(data, page_zip_get_size(&block->page.zip));
1663
buf_pool_mutex_exit_allow();
1752
1664
mutex_enter(&block->mutex);
1753
1665
page_zip_set_size(&block->page.zip, 0);
1762
1674
/******************************************************************//**
1763
1675
Takes a block out of the LRU list and page hash table.
1764
1676
If the block is compressed-only (BUF_BLOCK_ZIP_PAGE),
1765
the object will be freed and buf_pool->zip_mutex will be released.
1677
the object will be freed and buf_pool_zip_mutex will be released.
1767
1679
If a compressed page or a compressed-only block descriptor is freed,
1768
1680
other compressed pages or compressed-only block descriptors may be
1779
1691
ibool zip) /*!< in: TRUE if should remove also the
1780
1692
compressed page of an uncompressed page */
1783
1694
const buf_page_t* hashed_bpage;
1784
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
1787
ut_ad(buf_pool_mutex_own(buf_pool));
1696
ut_ad(buf_pool_mutex_own());
1788
1697
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1790
1699
ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1873
fold = buf_page_address_fold(bpage->space, bpage->offset);
1874
hashed_bpage = buf_page_hash_get_low(
1875
buf_pool, bpage->space, bpage->offset, fold);
1782
hashed_bpage = buf_page_hash_get(bpage->space, bpage->offset);
1877
1784
if (UNIV_UNLIKELY(bpage != hashed_bpage)) {
1878
1785
fprintf(stderr,
1904
1811
ut_ad(!bpage->in_zip_hash);
1905
1812
ut_ad(bpage->in_page_hash);
1906
1813
ut_d(bpage->in_page_hash = FALSE);
1907
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
1814
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash,
1815
buf_page_address_fold(bpage->space, bpage->offset),
1908
1817
switch (buf_page_get_state(bpage)) {
1909
1818
case BUF_BLOCK_ZIP_PAGE:
1910
1819
ut_ad(!bpage->in_free_list);
1916
1825
UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
1918
mutex_exit(&buf_pool->zip_mutex);
1919
buf_pool_mutex_exit_forbid(buf_pool);
1922
buf_pool, bpage->zip.data,
1923
page_zip_get_size(&bpage->zip));
1925
buf_buddy_free(buf_pool, bpage, sizeof(*bpage));
1926
buf_pool_mutex_exit_allow(buf_pool);
1827
mutex_exit(&buf_pool_zip_mutex);
1828
buf_pool_mutex_exit_forbid();
1829
buf_buddy_free(bpage->zip.data,
1830
page_zip_get_size(&bpage->zip));
1831
buf_buddy_free(bpage, sizeof(*bpage));
1832
buf_pool_mutex_exit_allow();
1928
1833
UNIV_MEM_UNDESC(bpage);
1929
1834
return(BUF_BLOCK_ZIP_FREE);
1946
1851
ut_ad(!bpage->in_flush_list);
1947
1852
ut_ad(!bpage->in_LRU_list);
1948
1853
mutex_exit(&((buf_block_t*) bpage)->mutex);
1949
buf_pool_mutex_exit_forbid(buf_pool);
1953
page_zip_get_size(&bpage->zip));
1955
buf_pool_mutex_exit_allow(buf_pool);
1854
buf_pool_mutex_exit_forbid();
1855
buf_buddy_free(data, page_zip_get_size(&bpage->zip));
1856
buf_pool_mutex_exit_allow();
1956
1857
mutex_enter(&((buf_block_t*) bpage)->mutex);
1957
1858
page_zip_set_size(&bpage->zip, 0);
1981
1882
buf_block_t* block) /*!< in: block, must contain a file page and
1982
1883
be in a state where it can be freed */
1985
buf_pool_t* buf_pool = buf_pool_from_block(block);
1986
ut_ad(buf_pool_mutex_own(buf_pool));
1885
ut_ad(buf_pool_mutex_own());
1988
1886
ut_ad(mutex_own(&block->mutex));
1990
1888
buf_block_set_state(block, BUF_BLOCK_MEMORY);
1995
1893
/**********************************************************************//**
1996
Updates buf_pool->LRU_old_ratio for one buffer pool instance.
1894
Updates buf_LRU_old_ratio.
1997
1895
@return updated old_pct */
2000
buf_LRU_old_ratio_update_instance(
2001
/*==============================*/
2002
buf_pool_t* buf_pool,/*!< in: buffer pool instance */
2003
uint old_pct,/*!< in: Reserve this percentage of
2004
the buffer pool for "old" blocks. */
2005
ibool adjust) /*!< in: TRUE=adjust the LRU list;
2006
FALSE=just assign buf_pool->LRU_old_ratio
2007
during the initialization of InnoDB */
1898
buf_LRU_old_ratio_update(
1899
/*=====================*/
1900
uint old_pct,/*!< in: Reserve this percentage of
1901
the buffer pool for "old" blocks. */
1902
ibool adjust) /*!< in: TRUE=adjust the LRU list;
1903
FALSE=just assign buf_LRU_old_ratio
1904
during the initialization of InnoDB */
2019
buf_pool_mutex_enter(buf_pool);
1916
buf_pool_mutex_enter();
2021
if (ratio != buf_pool->LRU_old_ratio) {
2022
buf_pool->LRU_old_ratio = ratio;
1918
if (ratio != buf_LRU_old_ratio) {
1919
buf_LRU_old_ratio = ratio;
2024
1921
if (UT_LIST_GET_LEN(buf_pool->LRU)
2025
>= BUF_LRU_OLD_MIN_LEN) {
2027
buf_LRU_old_adjust_len(buf_pool);
1922
>= BUF_LRU_OLD_MIN_LEN) {
1923
buf_LRU_old_adjust_len();
2031
buf_pool_mutex_exit(buf_pool);
1927
buf_pool_mutex_exit();
2033
buf_pool->LRU_old_ratio = ratio;
1929
buf_LRU_old_ratio = ratio;
2035
1932
/* the reverse of
2036
1933
ratio = old_pct * BUF_LRU_OLD_RATIO_DIV / 100 */
2037
1934
return((uint) (ratio * 100 / (double) BUF_LRU_OLD_RATIO_DIV + 0.5));
2040
/**********************************************************************//**
2041
Updates buf_pool->LRU_old_ratio.
2042
@return updated old_pct */
2045
buf_LRU_old_ratio_update(
2046
/*=====================*/
2047
uint old_pct,/*!< in: Reserve this percentage of
2048
the buffer pool for "old" blocks. */
2049
ibool adjust) /*!< in: TRUE=adjust the LRU list;
2050
FALSE=just assign buf_pool->LRU_old_ratio
2051
during the initialization of InnoDB */
2054
ulint new_ratio = 0;
2056
for (i = 0; i < srv_buf_pool_instances; i++) {
2057
buf_pool_t* buf_pool;
2059
buf_pool = buf_pool_from_array(i);
2061
new_ratio = buf_LRU_old_ratio_update_instance(
2062
buf_pool, old_pct, adjust);
2068
1937
/********************************************************************//**
2069
1938
Update the historical stats that we are collecting for LRU eviction
2070
1939
policy at the end of each interval. */
2073
1942
buf_LRU_stat_update(void)
2074
1943
/*=====================*/
2077
1945
buf_LRU_stat_t* item;
2078
buf_pool_t* buf_pool;
2079
ibool evict_started = FALSE;
2081
1947
/* If we haven't started eviction yet then don't update stats. */
2082
for (i = 0; i < srv_buf_pool_instances; i++) {
2084
buf_pool = buf_pool_from_array(i);
2086
if (buf_pool->freed_page_clock != 0) {
2087
evict_started = TRUE;
2092
if (!evict_started) {
1948
if (buf_pool->freed_page_clock == 0) {
2093
1949
goto func_exit;
1952
buf_pool_mutex_enter();
2096
1954
/* Update the index. */
2097
1955
item = &buf_LRU_stat_arr[buf_LRU_stat_arr_ind];
2098
1956
buf_LRU_stat_arr_ind++;
2105
1963
/* Put current entry in the array. */
2106
1964
memcpy(item, &buf_LRU_stat_cur, sizeof *item);
1966
buf_pool_mutex_exit();
2109
1969
/* Clear the current entry. */
2110
1970
memset(&buf_LRU_stat_cur, 0, sizeof buf_LRU_stat_cur);
2113
1973
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2114
1974
/**********************************************************************//**
2115
Validates the LRU list for one buffer pool instance. */
2118
buf_LRU_validate_instance(
2119
/*======================*/
2120
buf_pool_t* buf_pool)
1975
Validates the LRU list.
1979
buf_LRU_validate(void)
1980
/*==================*/
2122
1982
buf_page_t* bpage;
2123
1983
buf_block_t* block;
2127
1987
ut_ad(buf_pool);
2128
buf_pool_mutex_enter(buf_pool);
1988
buf_pool_mutex_enter();
2130
1990
if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
2132
1992
ut_a(buf_pool->LRU_old);
2133
1993
old_len = buf_pool->LRU_old_len;
2134
1994
new_len = ut_min(UT_LIST_GET_LEN(buf_pool->LRU)
2135
* buf_pool->LRU_old_ratio
2136
/ BUF_LRU_OLD_RATIO_DIV,
1995
* buf_LRU_old_ratio / BUF_LRU_OLD_RATIO_DIV,
2137
1996
UT_LIST_GET_LEN(buf_pool->LRU)
2138
1997
- (BUF_LRU_OLD_TOLERANCE
2139
1998
+ BUF_LRU_NON_OLD_MIN_LEN));
2209
2068
ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
2212
buf_pool_mutex_exit(buf_pool);
2215
/**********************************************************************//**
2216
Validates the LRU list.
2220
buf_LRU_validate(void)
2221
/*==================*/
2225
for (i = 0; i < srv_buf_pool_instances; i++) {
2226
buf_pool_t* buf_pool;
2228
buf_pool = buf_pool_from_array(i);
2229
buf_LRU_validate_instance(buf_pool);
2071
buf_pool_mutex_exit();
2234
2074
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
2236
2076
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2237
2077
/**********************************************************************//**
2238
Prints the LRU list for one buffer pool instance. */
2078
Prints the LRU list. */
2241
buf_LRU_print_instance(
2242
/*===================*/
2243
buf_pool_t* buf_pool)
2245
2084
const buf_page_t* bpage;
2247
2086
ut_ad(buf_pool);
2248
buf_pool_mutex_enter(buf_pool);
2087
buf_pool_mutex_enter();
2250
2089
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
2252
2091
while (bpage != NULL) {
2254
mutex_enter(buf_page_get_mutex(bpage));
2255
2093
fprintf(stderr, "BLOCK space %lu page %lu ",
2256
2094
(ulong) buf_page_get_space(bpage),
2257
2095
(ulong) buf_page_get_page_no(bpage));
2279
2117
case BUF_BLOCK_FILE_PAGE:
2280
2118
frame = buf_block_get_frame((buf_block_t*) bpage);
2281
2119
fprintf(stderr, "\ntype %lu"
2283
2121
(ulong) fil_page_get_type(frame),
2284
(ullint) btr_page_get_index_id(frame));
2122
(ulong) ut_dulint_get_low(
2123
btr_page_get_index_id(frame)));
2286
2125
case BUF_BLOCK_ZIP_PAGE:
2287
2126
frame = bpage->zip.data;
2288
2127
fprintf(stderr, "\ntype %lu size %lu"
2290
2129
(ulong) fil_page_get_type(frame),
2291
2130
(ulong) buf_page_get_zip_size(bpage),
2292
(ullint) btr_page_get_index_id(frame));
2131
(ulong) ut_dulint_get_low(
2132
btr_page_get_index_id(frame)));
2301
mutex_exit(buf_page_get_mutex(bpage));
2302
2141
bpage = UT_LIST_GET_NEXT(LRU, bpage);
2305
buf_pool_mutex_exit(buf_pool);
2308
/**********************************************************************//**
2309
Prints the LRU list. */
2316
buf_pool_t* buf_pool;
2318
for (i = 0; i < srv_buf_pool_instances; i++) {
2319
buf_pool = buf_pool_from_array(i);
2320
buf_LRU_print_instance(buf_pool);
2144
buf_pool_mutex_exit();
2323
2146
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */