66
111
be in a state where it can be freed */
68
113
/**********************************************************************
114
Determines if the unzip_LRU list should be used for evicting a victim
115
instead of the general LRU list. */
118
buf_LRU_evict_from_unzip_LRU(void)
119
/*==============================*/
120
/* out: TRUE if should use unzip_LRU */
125
ut_ad(buf_pool_mutex_own());
127
/* If the unzip_LRU list is empty, we can only use the LRU. */
128
if (UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0) {
132
/* If unzip_LRU is at most 10% of the size of the LRU list,
133
then use the LRU. This slack allows us to keep hot
134
decompressed pages in the buffer pool. */
135
if (UT_LIST_GET_LEN(buf_pool->unzip_LRU)
136
<= UT_LIST_GET_LEN(buf_pool->LRU) / 10) {
140
/* If eviction hasn't started yet, we assume by default
141
that a workload is disk bound. */
142
if (buf_pool->freed_page_clock == 0) {
146
/* Calculate the average over past intervals, and add the values
147
of the current interval. */
148
io_avg = buf_LRU_stat_sum.io / BUF_LRU_STAT_N_INTERVAL
149
+ buf_LRU_stat_cur.io;
150
unzip_avg = buf_LRU_stat_sum.unzip / BUF_LRU_STAT_N_INTERVAL
151
+ buf_LRU_stat_cur.unzip;
153
/* Decide based on our formula. If the load is I/O bound
154
(unzip_avg is smaller than the weighted io_avg), evict an
155
uncompressed frame from unzip_LRU. Otherwise we assume that
156
the load is CPU bound and evict from the regular LRU. */
157
return(unzip_avg <= io_avg * BUF_LRU_IO_TO_UNZIP_FACTOR);
160
/**********************************************************************
69
161
Invalidates all pages belonging to a given tablespace when we are deleting
70
162
the data file(s) of that tablespace. */
73
165
buf_LRU_invalidate_tablespace(
74
166
/*==========================*/
75
167
ulint id) /* in: space id */
82
mutex_enter(&(buf_pool->mutex));
174
buf_pool_mutex_enter();
86
block = UT_LIST_GET_LAST(buf_pool->LRU);
88
while (block != NULL) {
89
buf_block_t* prev_block;
91
mutex_enter(&block->mutex);
92
prev_block = UT_LIST_GET_PREV(LRU, block);
94
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
96
if (block->space == id
97
&& (block->buf_fix_count > 0 || block->io_fix != 0)) {
99
/* We cannot remove this page during this scan yet;
100
maybe the system is currently reading it in, or
101
flushing the modifications to the file */
108
if (block->space == id) {
178
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
180
while (bpage != NULL) {
181
mutex_t* block_mutex = buf_page_get_mutex(bpage);
182
buf_page_t* prev_bpage;
184
ut_a(buf_page_in_file(bpage));
186
mutex_enter(block_mutex);
187
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
189
if (buf_page_get_space(bpage) == id) {
190
if (bpage->buf_fix_count > 0
191
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
193
/* We cannot remove this page during
194
this scan yet; maybe the system is
195
currently reading it in, or flushing
196
the modifications to the file */
109
203
#ifdef UNIV_DEBUG
110
204
if (buf_debug_prints) {
112
206
"Dropping space %lu page %lu\n",
113
(ulong) block->space,
114
(ulong) block->offset);
207
(ulong) buf_page_get_space(bpage),
208
(ulong) buf_page_get_page_no(bpage));
117
if (block->is_hashed) {
118
page_no = block->offset;
120
mutex_exit(&block->mutex);
122
mutex_exit(&(buf_pool->mutex));
211
if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE
212
&& ((buf_block_t*) bpage)->is_hashed) {
213
page_no = buf_page_get_page_no(bpage);
215
buf_pool_mutex_exit();
216
mutex_exit(block_mutex);
124
218
/* Note that the following call will acquire
125
219
an S-latch on the page */
127
btr_search_drop_page_hash_when_freed(id,
221
btr_search_drop_page_hash_when_freed(
223
buf_page_get_zip_size(bpage),
132
if (0 != ut_dulint_cmp(block->oldest_modification,
135
/* Remove from the flush list of modified
137
block->oldest_modification = ut_dulint_zero;
139
UT_LIST_REMOVE(flush_list,
140
buf_pool->flush_list, block);
228
if (bpage->oldest_modification != 0) {
230
buf_flush_remove(bpage);
143
233
/* Remove from the LRU list */
144
buf_LRU_block_remove_hashed_page(block);
145
buf_LRU_block_free_hashed_page(block);
234
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
235
!= BUF_BLOCK_ZIP_FREE) {
236
buf_LRU_block_free_hashed_page((buf_block_t*)
239
/* The compressed block descriptor
240
(bpage) has been deallocated and
241
block_mutex released. Also,
242
buf_buddy_free() may have relocated
243
prev_bpage. Rescan the LRU list. */
245
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
148
mutex_exit(&block->mutex);
250
mutex_exit(block_mutex);
152
mutex_exit(&(buf_pool->mutex));
254
buf_pool_mutex_exit();
154
256
if (!all_freed) {
155
257
os_thread_sleep(20000);
162
264
Gets the minimum LRU_position field for the blocks in an initial segment
163
265
(determined by BUF_LRU_INITIAL_RATIO) of the LRU list. The limit is not
164
266
guaranteed to be precise, because the ulint_clock may wrap around. */
167
269
buf_LRU_get_recent_limit(void)
168
270
/*==========================*/
169
271
/* out: the limit; zero if could not determine it */
273
const buf_page_t* bpage;
175
mutex_enter(&(buf_pool->mutex));
277
buf_pool_mutex_enter();
177
279
len = UT_LIST_GET_LEN(buf_pool->LRU);
179
281
if (len < BUF_LRU_OLD_MIN_LEN) {
180
282
/* The LRU list is too short to do read-ahead */
182
mutex_exit(&(buf_pool->mutex));
284
buf_pool_mutex_exit();
187
block = UT_LIST_GET_FIRST(buf_pool->LRU);
189
limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO;
191
mutex_exit(&(buf_pool->mutex));
289
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
291
limit = buf_page_get_LRU_position(bpage) - len / BUF_LRU_INITIAL_RATIO;
293
buf_pool_mutex_exit();
196
/**********************************************************************
197
Look for a replaceable block from the end of the LRU list and put it to
198
the free list if found. */
298
/************************************************************************
299
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
302
buf_LRU_insert_zip_clean(
303
/*=====================*/
304
buf_page_t* bpage) /* in: pointer to the block in question */
308
ut_ad(buf_pool_mutex_own());
309
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
311
/* Find the first successor of bpage in the LRU list
312
that is in the zip_clean list. */
315
b = UT_LIST_GET_NEXT(LRU, b);
316
} while (b && buf_page_get_state(b) != BUF_BLOCK_ZIP_PAGE);
318
/* Insert bpage before b, i.e., after the predecessor of b. */
320
b = UT_LIST_GET_PREV(list, b);
324
UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, bpage);
326
UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, bpage);
330
/**********************************************************************
331
Try to free an uncompressed page of a compressed block from the unzip
332
LRU list. The compressed page is preserved, and it need not be clean. */
335
buf_LRU_free_from_unzip_LRU_list(
336
/*=============================*/
337
/* out: TRUE if freed */
338
ulint n_iterations) /* in: how many times this has been called
339
repeatedly without result: a high value means
340
that we should search farther; we will search
341
n_iterations / 5 of the unzip_LRU list,
342
or nothing if n_iterations >= 5 */
347
ut_ad(buf_pool_mutex_own());
349
/* Theoratically it should be much easier to find a victim
350
from unzip_LRU as we can choose even a dirty block (as we'll
351
be evicting only the uncompressed frame). In a very unlikely
352
eventuality that we are unable to find a victim from
353
unzip_LRU, we fall back to the regular LRU list. We do this
354
if we have done five iterations so far. */
356
if (UNIV_UNLIKELY(n_iterations >= 5)
357
|| !buf_LRU_evict_from_unzip_LRU()) {
362
distance = 100 + (n_iterations
363
* UT_LIST_GET_LEN(buf_pool->unzip_LRU)) / 5;
365
for (block = UT_LIST_GET_LAST(buf_pool->unzip_LRU);
366
UNIV_LIKELY(block != NULL) && UNIV_LIKELY(distance > 0);
367
block = UT_LIST_GET_PREV(unzip_LRU, block), distance--) {
369
enum buf_lru_free_block_status freed;
371
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
372
ut_ad(block->in_unzip_LRU_list);
373
ut_ad(block->page.in_LRU_list);
375
mutex_enter(&block->mutex);
376
freed = buf_LRU_free_block(&block->page, FALSE, NULL);
377
mutex_exit(&block->mutex);
383
case BUF_LRU_CANNOT_RELOCATE:
384
/* If we failed to relocate, try
385
regular LRU eviction. */
388
case BUF_LRU_NOT_FREED:
389
/* The block was buffer-fixed or I/O-fixed.
394
/* inappropriate return value from
395
buf_LRU_free_block() */
402
/**********************************************************************
403
Try to free a clean page from the common LRU list. */
406
buf_LRU_free_from_common_LRU_list(
407
/*==============================*/
408
/* out: TRUE if freed */
409
ulint n_iterations) /* in: how many times this has been called
410
repeatedly without result: a high value means
411
that we should search farther; if
412
n_iterations < 10, then we search
413
n_iterations / 10 * buf_pool->curr_size
414
pages from the end of the LRU list */
419
ut_ad(buf_pool_mutex_own());
421
distance = 100 + (n_iterations * buf_pool->curr_size) / 10;
423
for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
424
UNIV_LIKELY(bpage != NULL) && UNIV_LIKELY(distance > 0);
425
bpage = UT_LIST_GET_PREV(LRU, bpage), distance--) {
427
enum buf_lru_free_block_status freed;
429
= buf_page_get_mutex(bpage);
431
ut_ad(buf_page_in_file(bpage));
432
ut_ad(bpage->in_LRU_list);
434
mutex_enter(block_mutex);
435
freed = buf_LRU_free_block(bpage, TRUE, NULL);
436
mutex_exit(block_mutex);
442
case BUF_LRU_NOT_FREED:
443
/* The block was dirty, buffer-fixed, or I/O-fixed.
447
case BUF_LRU_CANNOT_RELOCATE:
448
/* This should never occur, because we
449
want to discard the compressed page too. */
453
/* inappropriate return value from
454
buf_LRU_free_block() */
461
/**********************************************************************
462
Try to free a replaceable block. */
201
465
buf_LRU_search_and_free_block(
202
466
/*==========================*/
203
/* out: TRUE if freed */
467
/* out: TRUE if found and freed */
204
468
ulint n_iterations) /* in: how many times this has been called
205
469
repeatedly without result: a high value means
206
that we should search farther; if value is
207
k < 10, then we only search k/10 * [number
208
of pages in the buffer pool] from the end
470
that we should search farther; if
471
n_iterations < 10, then we search
472
n_iterations / 10 * buf_pool->curr_size
473
pages from the end of the LRU list; if
474
n_iterations < 5, then we will also search
475
n_iterations / 5 of the unzip_LRU list. */
215
mutex_enter(&(buf_pool->mutex));
218
block = UT_LIST_GET_LAST(buf_pool->LRU);
220
while (block != NULL) {
221
ut_a(block->in_LRU_list);
223
mutex_enter(&block->mutex);
225
if (buf_flush_ready_for_replace(block)) {
228
if (buf_debug_prints) {
230
"Putting space %lu page %lu"
232
(ulong) block->space,
233
(ulong) block->offset);
235
#endif /* UNIV_DEBUG */
237
buf_LRU_block_remove_hashed_page(block);
239
mutex_exit(&(buf_pool->mutex));
240
mutex_exit(&block->mutex);
242
/* Remove possible adaptive hash index built on the
243
page; in the case of AWE the block may not have a
247
/* The page was declared uninitialized
248
by buf_LRU_block_remove_hashed_page().
249
We need to flag the contents of the
250
page valid (which it still is) in
251
order to avoid bogus Valgrind
253
UNIV_MEM_VALID(block->frame, UNIV_PAGE_SIZE);
254
btr_search_drop_page_hash_index(block->frame);
255
UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
258
ut_a(block->buf_fix_count == 0);
260
mutex_enter(&(buf_pool->mutex));
261
mutex_enter(&block->mutex);
263
buf_LRU_block_free_hashed_page(block);
265
mutex_exit(&block->mutex);
270
mutex_exit(&block->mutex);
272
block = UT_LIST_GET_PREV(LRU, block);
275
if (!freed && n_iterations <= 10
276
&& distance > 100 + (n_iterations * buf_pool->curr_size)
278
buf_pool->LRU_flush_ended = 0;
280
mutex_exit(&(buf_pool->mutex));
479
buf_pool_mutex_enter();
481
freed = buf_LRU_free_from_unzip_LRU_list(n_iterations);
484
freed = buf_LRU_free_from_common_LRU_list(n_iterations);
285
if (buf_pool->LRU_flush_ended > 0) {
488
buf_pool->LRU_flush_ended = 0;
489
} else if (buf_pool->LRU_flush_ended > 0) {
286
490
buf_pool->LRU_flush_ended--;
289
buf_pool->LRU_flush_ended = 0;
291
mutex_exit(&(buf_pool->mutex));
493
buf_pool_mutex_exit();
811
1072
buf_LRU_old_init();
1075
/* If this is a zipped block with decompressed frame as well
1076
then put it on the unzip_LRU list */
1077
if (buf_page_belongs_to_unzip_LRU(bpage)) {
1078
buf_unzip_LRU_add_block((buf_block_t*) bpage, old);
815
1082
/**********************************************************************
816
1083
Adds a block to the LRU list. */
819
1086
buf_LRU_add_block(
820
1087
/*==============*/
821
buf_block_t* block, /* in: control block */
1088
buf_page_t* bpage, /* in: control block */
822
1089
ibool old) /* in: TRUE if should be put to the old
823
1090
blocks in the LRU list, else put to the start;
824
1091
if the LRU list is very short, the block is
825
1092
added to the start, regardless of this
828
buf_LRU_add_block_low(block, old);
1095
buf_LRU_add_block_low(bpage, old);
831
1098
/**********************************************************************
832
1099
Moves a block to the start of the LRU list. */
835
1102
buf_LRU_make_block_young(
836
1103
/*=====================*/
837
buf_block_t* block) /* in: control block */
1104
buf_page_t* bpage) /* in: control block */
839
buf_LRU_remove_block(block);
840
buf_LRU_add_block_low(block, FALSE);
1106
buf_LRU_remove_block(bpage);
1107
buf_LRU_add_block_low(bpage, FALSE);
843
1110
/**********************************************************************
844
1111
Moves a block to the end of the LRU list. */
847
1114
buf_LRU_make_block_old(
848
1115
/*===================*/
849
buf_block_t* block) /* in: control block */
851
buf_LRU_remove_block(block);
852
buf_LRU_add_block_to_end_low(block);
1116
buf_page_t* bpage) /* in: control block */
1118
buf_LRU_remove_block(bpage);
1119
buf_LRU_add_block_to_end_low(bpage);
1122
/**********************************************************************
1123
Try to free a block. If bpage is a descriptor of a compressed-only
1124
page, the descriptor object will be freed as well. If this function
1125
returns BUF_LRU_FREED, it will not temporarily release
1128
enum buf_lru_free_block_status
1131
/* out: BUF_LRU_FREED if freed,
1132
BUF_LRU_CANNOT_RELOCATE or
1133
BUF_LRU_NOT_FREED otherwise. */
1134
buf_page_t* bpage, /* in: block to be freed */
1135
ibool zip, /* in: TRUE if should remove also the
1136
compressed page of an uncompressed page */
1137
ibool* buf_pool_mutex_released)
1138
/* in: pointer to a variable that will
1139
be assigned TRUE if buf_pool_mutex
1140
was temporarily released, or NULL */
1142
buf_page_t* b = NULL;
1143
mutex_t* block_mutex = buf_page_get_mutex(bpage);
1145
ut_ad(buf_pool_mutex_own());
1146
ut_ad(mutex_own(block_mutex));
1147
ut_ad(buf_page_in_file(bpage));
1148
ut_ad(bpage->in_LRU_list);
1149
ut_ad(!bpage->in_flush_list == !bpage->oldest_modification);
1150
UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
1152
if (!buf_page_can_relocate(bpage)) {
1154
/* Do not free buffer-fixed or I/O-fixed blocks. */
1155
return(BUF_LRU_NOT_FREED);
1158
if (zip || !bpage->zip.data) {
1159
/* This would completely free the block. */
1160
/* Do not completely free dirty blocks. */
1162
if (bpage->oldest_modification) {
1163
return(BUF_LRU_NOT_FREED);
1165
} else if (bpage->oldest_modification) {
1166
/* Do not completely free dirty blocks. */
1168
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
1169
ut_ad(buf_page_get_state(bpage)
1170
== BUF_BLOCK_ZIP_DIRTY);
1171
return(BUF_LRU_NOT_FREED);
1175
} else if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE) {
1176
/* Allocate the control block for the compressed page.
1177
If it cannot be allocated (without freeing a block
1178
from the LRU list), refuse to free bpage. */
1180
buf_pool_mutex_exit_forbid();
1181
b = buf_buddy_alloc(sizeof *b, NULL);
1182
buf_pool_mutex_exit_allow();
1184
if (UNIV_UNLIKELY(!b)) {
1185
return(BUF_LRU_CANNOT_RELOCATE);
1188
memcpy(b, bpage, sizeof *b);
1192
if (buf_debug_prints) {
1193
fprintf(stderr, "Putting space %lu page %lu to free list\n",
1194
(ulong) buf_page_get_space(bpage),
1195
(ulong) buf_page_get_page_no(bpage));
1197
#endif /* UNIV_DEBUG */
1199
if (buf_LRU_block_remove_hashed_page(bpage, zip)
1200
!= BUF_BLOCK_ZIP_FREE) {
1201
ut_a(bpage->buf_fix_count == 0);
1204
buf_page_t* prev_b = UT_LIST_GET_PREV(LRU, b);
1205
const ulint fold = buf_page_address_fold(
1206
bpage->space, bpage->offset);
1208
ut_a(!buf_page_hash_get(bpage->space, bpage->offset));
1210
b->state = b->oldest_modification
1211
? BUF_BLOCK_ZIP_DIRTY
1212
: BUF_BLOCK_ZIP_PAGE;
1213
UNIV_MEM_DESC(b->zip.data,
1214
page_zip_get_size(&b->zip), b);
1216
/* The fields in_page_hash and in_LRU_list of
1217
the to-be-freed block descriptor should have
1219
buf_LRU_block_remove_hashed_page(), which
1220
invokes buf_LRU_remove_block(). */
1221
ut_ad(!bpage->in_page_hash);
1222
ut_ad(!bpage->in_LRU_list);
1223
/* bpage->state was BUF_BLOCK_FILE_PAGE because
1224
b != NULL. The type cast below is thus valid. */
1225
ut_ad(!((buf_block_t*) bpage)->in_unzip_LRU_list);
1227
/* The fields of bpage were copied to b before
1228
buf_LRU_block_remove_hashed_page() was invoked. */
1229
ut_ad(!b->in_zip_hash);
1230
ut_ad(b->in_page_hash);
1231
ut_ad(b->in_LRU_list);
1233
HASH_INSERT(buf_page_t, hash,
1234
buf_pool->page_hash, fold, b);
1236
/* Insert b where bpage was in the LRU list. */
1237
if (UNIV_LIKELY(prev_b != NULL)) {
1240
ut_ad(prev_b->in_LRU_list);
1241
ut_ad(buf_page_in_file(prev_b));
1242
UNIV_MEM_ASSERT_RW(prev_b, sizeof *prev_b);
1244
UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU,
1247
if (buf_page_is_old(b)) {
1248
buf_pool->LRU_old_len++;
1251
lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
1253
if (lru_len > BUF_LRU_OLD_MIN_LEN) {
1254
ut_ad(buf_pool->LRU_old);
1255
/* Adjust the length of the
1256
old block list if necessary */
1257
buf_LRU_old_adjust_len();
1258
} else if (lru_len == BUF_LRU_OLD_MIN_LEN) {
1259
/* The LRU list is now long
1260
enough for LRU_old to become
1265
ut_d(b->in_LRU_list = FALSE);
1266
buf_LRU_add_block_low(b, buf_page_is_old(b));
1269
if (b->state == BUF_BLOCK_ZIP_PAGE) {
1270
buf_LRU_insert_zip_clean(b);
1274
ut_ad(b->in_flush_list);
1275
ut_d(bpage->in_flush_list = FALSE);
1277
prev = UT_LIST_GET_PREV(list, b);
1278
UT_LIST_REMOVE(list, buf_pool->flush_list, b);
1281
ut_ad(prev->in_flush_list);
1282
UT_LIST_INSERT_AFTER(
1284
buf_pool->flush_list,
1289
buf_pool->flush_list,
1294
bpage->zip.data = NULL;
1295
page_zip_set_size(&bpage->zip, 0);
1297
/* Prevent buf_page_get_gen() from
1298
decompressing the block while we release
1299
buf_pool_mutex and block_mutex. */
1301
b->io_fix = BUF_IO_READ;
1304
if (buf_pool_mutex_released) {
1305
*buf_pool_mutex_released = TRUE;
1308
buf_pool_mutex_exit();
1309
mutex_exit(block_mutex);
1311
/* Remove possible adaptive hash index on the page.
1312
The page was declared uninitialized by
1313
buf_LRU_block_remove_hashed_page(). We need to flag
1314
the contents of the page valid (which it still is) in
1315
order to avoid bogus Valgrind warnings.*/
1317
UNIV_MEM_VALID(((buf_block_t*) bpage)->frame,
1319
btr_search_drop_page_hash_index((buf_block_t*) bpage);
1320
UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1324
/* Compute and stamp the compressed page
1325
checksum while not holding any mutex. The
1326
block is already half-freed
1327
(BUF_BLOCK_REMOVE_HASH) and removed from
1328
buf_pool->page_hash, thus inaccessible by any
1332
b->zip.data + FIL_PAGE_SPACE_OR_CHKSUM,
1333
UNIV_LIKELY(srv_use_checksums)
1334
? page_zip_calc_checksum(
1336
page_zip_get_size(&b->zip))
1337
: BUF_NO_CHECKSUM_MAGIC);
1340
buf_pool_mutex_enter();
1341
mutex_enter(block_mutex);
1344
mutex_enter(&buf_pool_zip_mutex);
1346
buf_page_set_io_fix(b, BUF_IO_NONE);
1347
mutex_exit(&buf_pool_zip_mutex);
1350
buf_LRU_block_free_hashed_page((buf_block_t*) bpage);
1352
mutex_enter(block_mutex);
1355
return(BUF_LRU_FREED);
855
1358
/**********************************************************************
856
1359
Puts a block back to the free list. */
859
1362
buf_LRU_block_free_non_file_page(
860
1363
/*=============================*/
861
1364
buf_block_t* block) /* in: block, must not contain a file page */
864
ut_ad(mutex_own(&(buf_pool->mutex)));
1368
ut_ad(buf_pool_mutex_own());
865
1369
ut_ad(mutex_own(&block->mutex));
868
ut_a((block->state == BUF_BLOCK_MEMORY)
869
|| (block->state == BUF_BLOCK_READY_FOR_USE));
871
ut_a(block->n_pointers == 0);
872
ut_a(!block->in_free_list);
874
block->state = BUF_BLOCK_NOT_USED;
1372
switch (buf_block_get_state(block)) {
1373
case BUF_BLOCK_MEMORY:
1374
case BUF_BLOCK_READY_FOR_USE:
1380
ut_ad(block->n_pointers == 0);
1381
ut_ad(!block->page.in_free_list);
1382
ut_ad(!block->page.in_flush_list);
1383
ut_ad(!block->page.in_LRU_list);
1385
buf_block_set_state(block, BUF_BLOCK_NOT_USED);
876
1387
UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE);
877
1388
#ifdef UNIV_DEBUG
878
1389
/* Wipe contents of page to reveal possible stale pointers to it */
879
1390
memset(block->frame, '\0', UNIV_PAGE_SIZE);
1392
/* Wipe page_no and space_id */
1393
memset(block->frame + FIL_PAGE_OFFSET, 0xfe, 4);
1394
memset(block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xfe, 4);
881
UT_LIST_ADD_FIRST(free, buf_pool->free, block);
882
block->in_free_list = TRUE;
1396
data = block->page.zip.data;
1399
block->page.zip.data = NULL;
1400
mutex_exit(&block->mutex);
1401
buf_pool_mutex_exit_forbid();
1402
buf_buddy_free(data, page_zip_get_size(&block->page.zip));
1403
buf_pool_mutex_exit_allow();
1404
mutex_enter(&block->mutex);
1405
page_zip_set_size(&block->page.zip, 0);
1408
UT_LIST_ADD_FIRST(list, buf_pool->free, (&block->page));
1409
ut_d(block->page.in_free_list = TRUE);
884
1411
UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
886
if (srv_use_awe && block->frame) {
887
/* Add to the list of mapped pages */
889
UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
890
buf_pool->awe_LRU_free_mapped, block);
894
1414
/**********************************************************************
895
Takes a block out of the LRU list and page hash table and sets the block
896
state to BUF_BLOCK_REMOVE_HASH. */
1415
Takes a block out of the LRU list and page hash table.
1416
If the block is compressed-only (BUF_BLOCK_ZIP_PAGE),
1417
the object will be freed and buf_pool_zip_mutex will be released.
1419
If a compressed page or a compressed-only block descriptor is freed,
1420
other compressed pages or compressed-only block descriptors may be
899
1424
buf_LRU_block_remove_hashed_page(
900
1425
/*=============================*/
901
buf_block_t* block) /* in: block, must contain a file page and
1426
/* out: the new state of the block
1427
(BUF_BLOCK_ZIP_FREE if the state was
1428
BUF_BLOCK_ZIP_PAGE, or BUF_BLOCK_REMOVE_HASH
1430
buf_page_t* bpage, /* in: block, must contain a file page and
902
1431
be in a state where it can be freed; there
903
1432
may or may not be a hash index to the page */
1433
ibool zip) /* in: TRUE if should remove also the
1434
compressed page of an uncompressed page */
905
ut_ad(mutex_own(&(buf_pool->mutex)));
906
ut_ad(mutex_own(&block->mutex));
909
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
910
ut_a(block->io_fix == 0);
911
ut_a(block->buf_fix_count == 0);
912
ut_a(ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) == 0);
914
buf_LRU_remove_block(block);
1436
const buf_page_t* hashed_bpage;
1438
ut_ad(buf_pool_mutex_own());
1439
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1441
ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1442
ut_a(bpage->buf_fix_count == 0);
1444
UNIV_MEM_ASSERT_RW(bpage, sizeof *bpage);
1446
buf_LRU_remove_block(bpage);
916
1448
buf_pool->freed_page_clock += 1;
918
/* Note that if AWE is enabled the block may not have a frame at all */
920
buf_block_modify_clock_inc(block);
922
if (block != buf_page_hash_get(block->space, block->offset)) {
1450
switch (buf_page_get_state(bpage)) {
1451
case BUF_BLOCK_FILE_PAGE:
1452
UNIV_MEM_ASSERT_W(bpage, sizeof(buf_block_t));
1453
UNIV_MEM_ASSERT_W(((buf_block_t*) bpage)->frame,
1455
buf_block_modify_clock_inc((buf_block_t*) bpage);
1456
if (bpage->zip.data) {
1457
const page_t* page = ((buf_block_t*) bpage)->frame;
1459
ut_a(!zip || bpage->oldest_modification == 0);
1461
switch (UNIV_EXPECT(fil_page_get_type(page),
1463
case FIL_PAGE_TYPE_ALLOCATED:
1464
case FIL_PAGE_INODE:
1465
case FIL_PAGE_IBUF_BITMAP:
1466
case FIL_PAGE_TYPE_FSP_HDR:
1467
case FIL_PAGE_TYPE_XDES:
1468
/* These are essentially uncompressed pages. */
1470
/* InnoDB writes the data to the
1471
uncompressed page frame. Copy it
1472
to the compressed page, which will
1474
memcpy(bpage->zip.data, page,
1475
page_zip_get_size(&bpage->zip));
1478
case FIL_PAGE_TYPE_ZBLOB:
1479
case FIL_PAGE_TYPE_ZBLOB2:
1481
case FIL_PAGE_INDEX:
1482
#ifdef UNIV_ZIP_DEBUG
1483
ut_a(page_zip_validate(&bpage->zip, page));
1484
#endif /* UNIV_ZIP_DEBUG */
1493
case BUF_BLOCK_ZIP_PAGE:
1494
ut_a(bpage->oldest_modification == 0);
1495
UNIV_MEM_ASSERT_W(bpage->zip.data,
1496
page_zip_get_size(&bpage->zip));
1498
case BUF_BLOCK_ZIP_FREE:
1499
case BUF_BLOCK_ZIP_DIRTY:
1500
case BUF_BLOCK_NOT_USED:
1501
case BUF_BLOCK_READY_FOR_USE:
1502
case BUF_BLOCK_MEMORY:
1503
case BUF_BLOCK_REMOVE_HASH:
1508
hashed_bpage = buf_page_hash_get(bpage->space, bpage->offset);
1510
if (UNIV_UNLIKELY(bpage != hashed_bpage)) {
924
1512
"InnoDB: Error: page %lu %lu not found"
925
1513
" in the hash table\n",
926
(ulong) block->space,
927
(ulong) block->offset);
928
if (buf_page_hash_get(block->space, block->offset)) {
1514
(ulong) bpage->space,
1515
(ulong) bpage->offset);
930
1518
"InnoDB: In hash table we find block"
931
1519
" %p of %lu %lu which is not %p\n",
932
(void*) buf_page_hash_get
933
(block->space, block->offset),
934
(ulong) buf_page_hash_get
935
(block->space, block->offset)->space,
936
(ulong) buf_page_hash_get
937
(block->space, block->offset)->offset,
1520
(const void*) hashed_bpage,
1521
(ulong) hashed_bpage->space,
1522
(ulong) hashed_bpage->offset,
1523
(const void*) bpage);
1526
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1527
mutex_exit(buf_page_get_mutex(bpage));
1528
buf_pool_mutex_exit();
943
1530
buf_LRU_print();
945
1532
buf_LRU_validate();
950
HASH_DELETE(buf_block_t, hash, buf_pool->page_hash,
951
buf_page_address_fold(block->space, block->offset),
954
UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
955
block->state = BUF_BLOCK_REMOVE_HASH;
1533
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1537
ut_ad(!bpage->in_zip_hash);
1538
ut_ad(bpage->in_page_hash);
1539
ut_d(bpage->in_page_hash = FALSE);
1540
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash,
1541
buf_page_address_fold(bpage->space, bpage->offset),
1543
switch (buf_page_get_state(bpage)) {
1544
case BUF_BLOCK_ZIP_PAGE:
1545
ut_ad(!bpage->in_free_list);
1546
ut_ad(!bpage->in_flush_list);
1547
ut_ad(!bpage->in_LRU_list);
1548
ut_a(bpage->zip.data);
1549
ut_a(buf_page_get_zip_size(bpage));
1551
UT_LIST_REMOVE(list, buf_pool->zip_clean, bpage);
1553
mutex_exit(&buf_pool_zip_mutex);
1554
buf_pool_mutex_exit_forbid();
1555
buf_buddy_free(bpage->zip.data,
1556
page_zip_get_size(&bpage->zip));
1557
buf_buddy_free(bpage, sizeof(*bpage));
1558
buf_pool_mutex_exit_allow();
1559
UNIV_MEM_UNDESC(bpage);
1560
return(BUF_BLOCK_ZIP_FREE);
1562
case BUF_BLOCK_FILE_PAGE:
1563
memset(((buf_block_t*) bpage)->frame
1564
+ FIL_PAGE_OFFSET, 0xff, 4);
1565
memset(((buf_block_t*) bpage)->frame
1566
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, 0xff, 4);
1567
UNIV_MEM_INVALID(((buf_block_t*) bpage)->frame,
1569
buf_page_set_state(bpage, BUF_BLOCK_REMOVE_HASH);
1571
if (zip && bpage->zip.data) {
1572
/* Free the compressed page. */
1573
void* data = bpage->zip.data;
1574
bpage->zip.data = NULL;
1576
mutex_exit(&((buf_block_t*) bpage)->mutex);
1577
buf_buddy_free(data, page_zip_get_size(&bpage->zip));
1578
mutex_enter(&((buf_block_t*) bpage)->mutex);
1579
page_zip_set_size(&bpage->zip, 0);
1582
return(BUF_BLOCK_REMOVE_HASH);
1584
case BUF_BLOCK_ZIP_FREE:
1585
case BUF_BLOCK_ZIP_DIRTY:
1586
case BUF_BLOCK_NOT_USED:
1587
case BUF_BLOCK_READY_FOR_USE:
1588
case BUF_BLOCK_MEMORY:
1589
case BUF_BLOCK_REMOVE_HASH:
1594
return(BUF_BLOCK_ZIP_FREE);
958
1597
/**********************************************************************
1033
1721
ut_a(buf_pool->LRU_old_len == old_len);
1036
UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free);
1038
block = UT_LIST_GET_FIRST(buf_pool->free);
1040
while (block != NULL) {
1041
ut_a(block->state == BUF_BLOCK_NOT_USED);
1043
block = UT_LIST_GET_NEXT(free, block);
1046
mutex_exit(&(buf_pool->mutex));
1724
UT_LIST_VALIDATE(list, buf_page_t, buf_pool->free);
1726
for (bpage = UT_LIST_GET_FIRST(buf_pool->free);
1728
bpage = UT_LIST_GET_NEXT(list, bpage)) {
1730
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_NOT_USED);
1733
UT_LIST_VALIDATE(unzip_LRU, buf_block_t, buf_pool->unzip_LRU);
1735
for (block = UT_LIST_GET_FIRST(buf_pool->unzip_LRU);
1737
block = UT_LIST_GET_NEXT(unzip_LRU, block)) {
1739
ut_ad(block->in_unzip_LRU_list);
1740
ut_ad(block->page.in_LRU_list);
1741
ut_a(buf_page_belongs_to_unzip_LRU(&block->page));
1744
buf_pool_mutex_exit();
1747
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1749
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1050
1750
/**************************************************************************
1051
1751
Prints the LRU list. */
1054
1754
buf_LRU_print(void)
1055
1755
/*===============*/
1757
const buf_page_t* bpage;
1061
1759
ut_ad(buf_pool);
1062
mutex_enter(&(buf_pool->mutex));
1760
buf_pool_mutex_enter();
1064
1762
fprintf(stderr, "Pool ulint clock %lu\n",
1065
1763
(ulong) buf_pool->ulint_clock);
1067
block = UT_LIST_GET_FIRST(buf_pool->LRU);
1071
while (block != NULL) {
1073
fprintf(stderr, "BLOCK %lu ", (ulong) block->offset);
1765
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
1767
while (bpage != NULL) {
1769
fprintf(stderr, "BLOCK space %lu page %lu ",
1770
(ulong) buf_page_get_space(bpage),
1771
(ulong) buf_page_get_page_no(bpage));
1773
if (buf_page_is_old(bpage)) {
1076
1774
fputs("old ", stderr);
1079
if (block->buf_fix_count) {
1777
if (bpage->buf_fix_count) {
1080
1778
fprintf(stderr, "buffix count %lu ",
1081
(ulong) block->buf_fix_count);
1084
if (block->io_fix) {
1085
fprintf(stderr, "io_fix %lu ", (ulong) block->io_fix);
1088
if (ut_dulint_cmp(block->oldest_modification,
1089
ut_dulint_zero) > 0) {
1779
(ulong) bpage->buf_fix_count);
1782
if (buf_page_get_io_fix(bpage)) {
1783
fprintf(stderr, "io_fix %lu ",
1784
(ulong) buf_page_get_io_fix(bpage));
1787
if (bpage->oldest_modification) {
1090
1788
fputs("modif. ", stderr);
1093
frame = buf_block_get_frame(block);
1095
fprintf(stderr, "LRU pos %lu type %lu index id %lu ",
1096
(ulong) block->LRU_position,
1097
(ulong) fil_page_get_type(frame),
1098
(ulong) ut_dulint_get_low
1099
(btr_page_get_index_id(frame)));
1101
block = UT_LIST_GET_NEXT(LRU, block);
1791
switch (buf_page_get_state(bpage)) {
1793
case BUF_BLOCK_FILE_PAGE:
1794
frame = buf_block_get_frame((buf_block_t*) bpage);
1795
fprintf(stderr, "\nLRU pos %lu type %lu"
1797
(ulong) buf_page_get_LRU_position(bpage),
1798
(ulong) fil_page_get_type(frame),
1799
(ulong) ut_dulint_get_low(
1800
btr_page_get_index_id(frame)));
1802
case BUF_BLOCK_ZIP_PAGE:
1803
frame = bpage->zip.data;
1804
fprintf(stderr, "\nLRU pos %lu type %lu size %lu"
1806
(ulong) buf_page_get_LRU_position(bpage),
1807
(ulong) fil_page_get_type(frame),
1808
(ulong) buf_page_get_zip_size(bpage),
1809
(ulong) ut_dulint_get_low(
1810
btr_page_get_index_id(frame)));
1814
fprintf(stderr, "\nLRU pos %lu !state %lu!\n",
1815
(ulong) buf_page_get_LRU_position(bpage),
1816
(ulong) buf_page_get_state(bpage));
1820
bpage = UT_LIST_GET_NEXT(LRU, bpage);
1108
mutex_exit(&(buf_pool->mutex));
1823
buf_pool_mutex_exit();
1110
#endif /* UNIV_DEBUG */
1825
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */