555
675
/************************************************************************
676
Allocates a chunk of buffer frames. */
681
/* out: chunk, or NULL on failure */
682
buf_chunk_t* chunk, /* out: chunk of buffers */
683
ulint mem_size) /* in: requested size in bytes */
689
/* Round down to a multiple of page size,
690
although it already should be. */
691
mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
692
/* Reserve space for the block descriptors. */
693
mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
694
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
696
chunk->mem_size = mem_size;
697
chunk->mem = os_mem_alloc_large(&chunk->mem_size);
699
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
704
/* Allocate the block descriptors from
705
the start of the memory block. */
706
chunk->blocks = chunk->mem;
708
/* Align a pointer to the first frame. Note that when
709
os_large_page_size is smaller than UNIV_PAGE_SIZE,
710
we may allocate one fewer block than requested. When
711
it is bigger, we may allocate more blocks than requested. */
713
frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
714
chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
715
- (frame != chunk->mem);
717
/* Subtract the space needed for block descriptors. */
719
ulint size = chunk->size;
721
while (frame < (byte*) (chunk->blocks + size)) {
722
frame += UNIV_PAGE_SIZE;
729
/* Init block structs and assign frames for them. Then we
730
assign the frames to the first blocks (we already mapped the
733
block = chunk->blocks;
735
for (i = chunk->size; i--; ) {
737
buf_block_init(block, frame);
740
/* Wipe contents of frame to eliminate a Purify warning */
741
memset(block->frame, '\0', UNIV_PAGE_SIZE);
743
/* Add the block to the free list */
744
UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
745
ut_d(block->page.in_free_list = TRUE);
748
frame += UNIV_PAGE_SIZE;
755
/*************************************************************************
756
Finds a block in the given buffer chunk that points to a
757
given compressed page. */
760
buf_chunk_contains_zip(
761
/*===================*/
762
/* out: buffer block pointing to
763
the compressed page, or NULL */
764
buf_chunk_t* chunk, /* in: chunk being checked */
765
const void* data) /* in: pointer to compressed page */
771
ut_ad(buf_pool_mutex_own());
773
block = chunk->blocks;
775
for (i = chunk->size; i--; block++) {
776
if (block->page.zip.data == data) {
785
/*************************************************************************
786
Finds a block in the buffer pool that points to a
787
given compressed page. */
790
buf_pool_contains_zip(
791
/*==================*/
792
/* out: buffer block pointing to
793
the compressed page, or NULL */
794
const void* data) /* in: pointer to compressed page */
797
buf_chunk_t* chunk = buf_pool->chunks;
799
for (n = buf_pool->n_chunks; n--; chunk++) {
800
buf_block_t* block = buf_chunk_contains_zip(chunk, data);
809
#endif /* UNIV_DEBUG */
811
/*************************************************************************
812
Checks that all file pages in the buffer chunk are in a replaceable state. */
817
/* out: address of a non-free block,
818
or NULL if all freed */
819
buf_chunk_t* chunk) /* in: chunk being checked */
825
ut_ad(buf_pool_mutex_own());
827
block = chunk->blocks;
829
for (i = chunk->size; i--; block++) {
830
mutex_enter(&block->mutex);
832
if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
833
&& !buf_flush_ready_for_replace(&block->page)) {
835
mutex_exit(&block->mutex);
839
mutex_exit(&block->mutex);
845
/*************************************************************************
846
Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state. */
851
/* out: TRUE if all freed */
852
const buf_chunk_t* chunk) /* in: chunk being checked */
854
const buf_block_t* block;
858
ut_ad(buf_pool_mutex_own());
860
block = chunk->blocks;
862
for (i = chunk->size; i--; block++) {
864
if (buf_block_get_state(block) != BUF_BLOCK_NOT_USED) {
873
/************************************************************************
874
Frees a chunk of buffer frames. */
879
buf_chunk_t* chunk) /* out: chunk of buffers */
882
const buf_block_t* block_end;
884
ut_ad(buf_pool_mutex_own());
886
block_end = chunk->blocks + chunk->size;
888
for (block = chunk->blocks; block < block_end; block++) {
889
ut_a(buf_block_get_state(block) == BUF_BLOCK_NOT_USED);
890
ut_a(!block->page.zip.data);
892
ut_ad(!block->page.in_LRU_list);
893
ut_ad(!block->in_unzip_LRU_list);
894
ut_ad(!block->page.in_flush_list);
895
/* Remove the block from the free list. */
896
ut_ad(block->page.in_free_list);
897
UT_LIST_REMOVE(list, buf_pool->free, (&block->page));
899
/* Free the latches. */
900
mutex_free(&block->mutex);
901
rw_lock_free(&block->lock);
902
#ifdef UNIV_SYNC_DEBUG
903
rw_lock_free(&block->debug_latch);
904
#endif /* UNIV_SYNC_DEBUG */
905
UNIV_MEM_UNDESC(block);
908
os_mem_free_large(chunk->mem, chunk->mem_size);
911
/************************************************************************
556
912
Creates the buffer pool. */
561
917
/* out, own: buf_pool object, NULL if not
562
918
enough memory or error */
563
ulint max_size, /* in: maximum size of the buf_pool in
565
ulint curr_size, /* in: current size to use, must be <=
566
max_size, currently must be equal to
568
ulint n_frames) /* in: number of frames; if AWE is used,
569
this is the size of the address space window
570
where physical memory pages are mapped; if
571
AWE is not used then this must be the same
578
ut_a(max_size == curr_size);
579
ut_a(srv_use_awe || n_frames == max_size);
581
if (n_frames > curr_size) {
583
"InnoDB: AWE: Error: you must specify in my.cnf"
584
" .._awe_mem_mb larger\n"
585
"InnoDB: than .._buffer_pool_size. Now the former"
587
"InnoDB: the latter %lu pages.\n",
588
(ulong) curr_size, (ulong) n_frames);
593
buf_pool = mem_alloc(sizeof(buf_pool_t));
923
buf_pool = mem_zalloc(sizeof(buf_pool_t));
595
925
/* 1. Initialize general fields
596
---------------------------- */
597
mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
599
mutex_enter(&(buf_pool->mutex));
602
/*----------------------------------------*/
603
/* Allocate the virtual address space window, i.e., the
604
buffer pool frames */
606
buf_pool->frame_mem = os_awe_allocate_virtual_mem_window(
607
UNIV_PAGE_SIZE * (n_frames + 1));
609
/* Allocate the physical memory for AWE and the AWE info array
612
if ((curr_size % ((1024 * 1024) / UNIV_PAGE_SIZE)) != 0) {
615
"InnoDB: AWE: Error: physical memory must be"
616
" allocated in full megabytes.\n"
617
"InnoDB: Trying to allocate %lu"
618
" database pages.\n",
624
if (!os_awe_allocate_physical_mem(&(buf_pool->awe_info),
627
/ UNIV_PAGE_SIZE))) {
631
/*----------------------------------------*/
633
buf_pool->frame_mem = os_mem_alloc_large(
634
UNIV_PAGE_SIZE * (n_frames + 1), TRUE, FALSE);
637
if (buf_pool->frame_mem == NULL) {
642
buf_pool->blocks = ut_malloc(sizeof(buf_block_t) * max_size);
644
if (buf_pool->blocks == NULL) {
649
buf_pool->max_size = max_size;
650
buf_pool->curr_size = curr_size;
652
buf_pool->n_frames = n_frames;
654
/* Align pointer to the first frame */
656
frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE);
658
buf_pool->frame_zero = frame;
659
buf_pool->high_end = frame + UNIV_PAGE_SIZE * n_frames;
662
/*----------------------------------------*/
663
/* Map an initial part of the allocated physical memory to
666
os_awe_map_physical_mem_to_window(buf_pool->frame_zero,
669
/ OS_AWE_X86_PAGE_SIZE),
671
/*----------------------------------------*/
674
buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames);
676
if (buf_pool->blocks_of_frames == NULL) {
681
/* Init block structs and assign frames for them; in the case of
682
AWE there are less frames than blocks. Then we assign the frames
683
to the first blocks (we already mapped the memory above). We also
684
init the awe_info for every block. */
686
for (i = 0; i < max_size; i++) {
688
block = buf_pool_get_nth_block(buf_pool, i);
691
frame = buf_pool->frame_zero + i * UNIV_PAGE_SIZE;
692
*(buf_pool->blocks_of_frames + i) = block;
697
buf_block_init(block, frame);
700
/*----------------------------------------*/
701
block->awe_info = buf_pool->awe_info
702
+ i * (UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE);
703
/*----------------------------------------*/
707
buf_pool->page_hash = hash_create(2 * max_size);
709
buf_pool->n_pend_reads = 0;
926
------------------------------- */
927
mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
928
mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
930
buf_pool_mutex_enter();
932
buf_pool->n_chunks = 1;
933
buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
935
UT_LIST_INIT(buf_pool->free);
937
if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
944
srv_buf_pool_old_size = srv_buf_pool_size;
945
buf_pool->curr_size = chunk->size;
946
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
948
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
949
buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
711
951
buf_pool->last_printout_time = time(NULL);
713
buf_pool->n_pages_read = 0;
714
buf_pool->n_pages_written = 0;
715
buf_pool->n_pages_created = 0;
716
buf_pool->n_pages_awe_remapped = 0;
718
buf_pool->n_page_gets = 0;
719
buf_pool->n_page_gets_old = 0;
720
buf_pool->n_pages_read_old = 0;
721
buf_pool->n_pages_written_old = 0;
722
buf_pool->n_pages_created_old = 0;
723
buf_pool->n_pages_awe_remapped_old = 0;
725
953
/* 2. Initialize flushing fields
726
---------------------------- */
727
UT_LIST_INIT(buf_pool->flush_list);
954
-------------------------------- */
729
for (i = BUF_FLUSH_LRU; i <= BUF_FLUSH_LIST; i++) {
730
buf_pool->n_flush[i] = 0;
731
buf_pool->init_flush[i] = FALSE;
956
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
732
957
buf_pool->no_flush[i] = os_event_create(NULL);
735
buf_pool->LRU_flush_ended = 0;
737
960
buf_pool->ulint_clock = 1;
738
buf_pool->freed_page_clock = 0;
740
962
/* 3. Initialize LRU fields
741
---------------------------- */
742
UT_LIST_INIT(buf_pool->LRU);
744
buf_pool->LRU_old = NULL;
746
UT_LIST_INIT(buf_pool->awe_LRU_free_mapped);
748
/* Add control blocks to the free list */
749
UT_LIST_INIT(buf_pool->free);
751
for (i = 0; i < curr_size; i++) {
753
block = buf_pool_get_nth_block(buf_pool, i);
756
/* Wipe contents of frame to eliminate a Purify
760
memset(block->frame, '\0', UNIV_PAGE_SIZE);
763
/* Add to the list of blocks mapped to
766
UT_LIST_ADD_LAST(awe_LRU_free_mapped,
767
buf_pool->awe_LRU_free_mapped,
772
UT_LIST_ADD_LAST(free, buf_pool->free, block);
773
block->in_free_list = TRUE;
776
mutex_exit(&(buf_pool->mutex));
778
if (srv_use_adaptive_hash_indexes) {
779
btr_search_sys_create(curr_size * UNIV_PAGE_SIZE
780
/ sizeof(void*) / 64);
782
/* Create only a small dummy system */
783
btr_search_sys_create(1000);
963
--------------------------- */
964
/* All fields are initialized by mem_zalloc(). */
966
buf_pool_mutex_exit();
968
btr_search_sys_create(buf_pool->curr_size
969
* UNIV_PAGE_SIZE / sizeof(void*) / 64);
971
/* 4. Initialize the buddy allocator fields */
972
/* All fields are initialized by mem_zalloc(). */
786
974
return(buf_pool);
789
977
/************************************************************************
790
Maps the page of block to a frame, if not mapped yet. Unmaps some page
791
from the end of the awe_LRU_free_mapped. */
794
buf_awe_map_page_to_frame(
795
/*======================*/
796
buf_block_t* block, /* in: block whose page should be
798
ibool add_to_mapped_list) /* in: TRUE if we in the case
799
we need to map the page should also
801
awe_LRU_free_mapped list */
805
ut_ad(mutex_own(&(buf_pool->mutex)));
978
Frees the buffer pool at shutdown. This must not be invoked before
979
freeing all mutexes. */
988
chunks = buf_pool->chunks;
989
chunk = chunks + buf_pool->n_chunks;
991
while (--chunk >= chunks) {
992
/* Bypass the checks of buf_chunk_free(), since they
993
would fail at shutdown. */
994
os_mem_free_large(chunk->mem, chunk->mem_size);
997
buf_pool->n_chunks = 0;
1000
/************************************************************************
1001
Relocate a buffer control block. Relocates the block on the LRU list
1002
and in buf_pool->page_hash. Does not relocate bpage->list.
1003
The caller must take care of relocating bpage->list. */
1008
buf_page_t* bpage, /* in/out: control block being relocated;
1009
buf_page_get_state(bpage) must be
1010
BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
1011
buf_page_t* dpage) /* in/out: destination control block */
1016
ut_ad(buf_pool_mutex_own());
1017
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1018
ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1019
ut_a(bpage->buf_fix_count == 0);
1020
ut_ad(bpage->in_LRU_list);
1021
ut_ad(!bpage->in_zip_hash);
1022
ut_ad(bpage->in_page_hash);
1023
ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
1025
switch (buf_page_get_state(bpage)) {
1026
case BUF_BLOCK_ZIP_FREE:
1027
case BUF_BLOCK_NOT_USED:
1028
case BUF_BLOCK_READY_FOR_USE:
1029
case BUF_BLOCK_FILE_PAGE:
1030
case BUF_BLOCK_MEMORY:
1031
case BUF_BLOCK_REMOVE_HASH:
1033
case BUF_BLOCK_ZIP_DIRTY:
1034
case BUF_BLOCK_ZIP_PAGE:
1037
#endif /* UNIV_DEBUG */
1039
memcpy(dpage, bpage, sizeof *dpage);
1041
ut_d(bpage->in_LRU_list = FALSE);
1042
ut_d(bpage->in_page_hash = FALSE);
1044
/* relocate buf_pool->LRU */
1045
b = UT_LIST_GET_PREV(LRU, bpage);
1046
UT_LIST_REMOVE(LRU, buf_pool->LRU, bpage);
1049
UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, b, dpage);
1051
UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, dpage);
1054
if (UNIV_UNLIKELY(buf_pool->LRU_old == bpage)) {
1055
buf_pool->LRU_old = dpage;
1058
ut_d(UT_LIST_VALIDATE(LRU, buf_page_t, buf_pool->LRU));
1060
/* relocate buf_pool->page_hash */
1061
fold = buf_page_address_fold(bpage->space, bpage->offset);
1063
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
1064
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
1066
UNIV_MEM_INVALID(bpage, sizeof *bpage);
1069
/************************************************************************
1070
Shrinks the buffer pool. */
1075
/* out: TRUE if shrunk */
1076
ulint chunk_size) /* in: number of pages to remove */
1078
buf_chunk_t* chunks;
1081
ulint max_free_size;
1082
buf_chunk_t* max_chunk;
1083
buf_chunk_t* max_free_chunk;
1085
ut_ad(!buf_pool_mutex_own());
1088
btr_search_disable(); /* Empty the adaptive hash index again */
1089
buf_pool_mutex_enter();
1092
if (buf_pool->n_chunks <= 1) {
1094
/* Cannot shrink if there is only one chunk */
1098
/* Search for the largest free chunk
1099
not larger than the size difference */
1100
chunks = buf_pool->chunks;
1101
chunk = chunks + buf_pool->n_chunks;
1102
max_size = max_free_size = 0;
1103
max_chunk = max_free_chunk = NULL;
1105
while (--chunk >= chunks) {
1106
if (chunk->size <= chunk_size
1107
&& chunk->size > max_free_size) {
1108
if (chunk->size > max_size) {
1109
max_size = chunk->size;
1113
if (buf_chunk_all_free(chunk)) {
1114
max_free_size = chunk->size;
1115
max_free_chunk = chunk;
1120
if (!max_free_size) {
1127
/* Cannot shrink: try again later
1128
(do not assign srv_buf_pool_old_size) */
1134
block = max_chunk->blocks;
1135
bend = block + max_chunk->size;
1137
/* Move the blocks of chunk to the end of the
1138
LRU list and try to flush them. */
1139
for (; block < bend; block++) {
1140
switch (buf_block_get_state(block)) {
1141
case BUF_BLOCK_NOT_USED:
1143
case BUF_BLOCK_FILE_PAGE:
1150
mutex_enter(&block->mutex);
1151
/* The following calls will temporarily
1152
release block->mutex and buf_pool_mutex.
1153
Therefore, we have to always retry,
1154
even if !dirty && !nonfree. */
1156
if (!buf_flush_ready_for_replace(&block->page)) {
1158
buf_LRU_make_block_old(&block->page);
1160
} else if (buf_LRU_free_block(&block->page, TRUE, NULL)
1165
mutex_exit(&block->mutex);
1168
buf_pool_mutex_exit();
1170
/* Request for a flush of the chunk if it helps.
1171
Do not flush if there are non-free blocks, since
1172
flushing will not make the chunk freeable. */
1174
/* Avoid busy-waiting. */
1175
os_thread_sleep(100000);
1177
&& buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
1178
== ULINT_UNDEFINED) {
1180
buf_flush_wait_batch_end(BUF_FLUSH_LRU);
1186
max_size = max_free_size;
1187
max_chunk = max_free_chunk;
1189
srv_buf_pool_old_size = srv_buf_pool_size;
1191
/* Rewrite buf_pool->chunks. Copy everything but max_chunk. */
1192
chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
1193
memcpy(chunks, buf_pool->chunks,
1194
(max_chunk - buf_pool->chunks) * sizeof *chunks);
1195
memcpy(chunks + (max_chunk - buf_pool->chunks),
1197
buf_pool->chunks + buf_pool->n_chunks
1199
ut_a(buf_pool->curr_size > max_chunk->size);
1200
buf_pool->curr_size -= max_chunk->size;
1201
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1202
chunk_size -= max_chunk->size;
1203
buf_chunk_free(max_chunk);
1204
mem_free(buf_pool->chunks);
1205
buf_pool->chunks = chunks;
1206
buf_pool->n_chunks--;
1208
/* Allow a slack of one megabyte. */
1209
if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
1215
srv_buf_pool_old_size = srv_buf_pool_size;
1217
buf_pool_mutex_exit();
1218
btr_search_enable();
1221
/************************************************************************
1222
Rebuild buf_pool->page_hash. */
1225
buf_pool_page_hash_rebuild(void)
1226
/*============================*/
1231
hash_table_t* page_hash;
1232
hash_table_t* zip_hash;
1235
buf_pool_mutex_enter();
1237
/* Free, create, and populate the hash table. */
1238
hash_table_free(buf_pool->page_hash);
1239
buf_pool->page_hash = page_hash = hash_create(2 * buf_pool->curr_size);
1240
zip_hash = hash_create(2 * buf_pool->curr_size);
1242
HASH_MIGRATE(buf_pool->zip_hash, zip_hash, buf_page_t, hash,
1243
BUF_POOL_ZIP_FOLD_BPAGE);
1245
hash_table_free(buf_pool->zip_hash);
1246
buf_pool->zip_hash = zip_hash;
1248
/* Insert the uncompressed file pages to buf_pool->page_hash. */
1250
chunk = buf_pool->chunks;
1251
n_chunks = buf_pool->n_chunks;
1253
for (i = 0; i < n_chunks; i++, chunk++) {
1255
buf_block_t* block = chunk->blocks;
1257
for (j = 0; j < chunk->size; j++, block++) {
1258
if (buf_block_get_state(block)
1259
== BUF_BLOCK_FILE_PAGE) {
1260
ut_ad(!block->page.in_zip_hash);
1261
ut_ad(block->page.in_page_hash);
1263
HASH_INSERT(buf_page_t, hash, page_hash,
1264
buf_page_address_fold(
1266
block->page.offset),
1272
/* Insert the compressed-only pages to buf_pool->page_hash.
1273
All such blocks are either in buf_pool->zip_clean or
1274
in buf_pool->flush_list. */
1276
for (b = UT_LIST_GET_FIRST(buf_pool->zip_clean); b;
1277
b = UT_LIST_GET_NEXT(list, b)) {
1278
ut_a(buf_page_get_state(b) == BUF_BLOCK_ZIP_PAGE);
1279
ut_ad(!b->in_flush_list);
1280
ut_ad(b->in_LRU_list);
1281
ut_ad(b->in_page_hash);
1282
ut_ad(!b->in_zip_hash);
1284
HASH_INSERT(buf_page_t, hash, page_hash,
1285
buf_page_address_fold(b->space, b->offset), b);
1288
for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1289
b = UT_LIST_GET_NEXT(list, b)) {
1290
ut_ad(b->in_flush_list);
1291
ut_ad(b->in_LRU_list);
1292
ut_ad(b->in_page_hash);
1293
ut_ad(!b->in_zip_hash);
1295
switch (buf_page_get_state(b)) {
1296
case BUF_BLOCK_ZIP_DIRTY:
1297
HASH_INSERT(buf_page_t, hash, page_hash,
1298
buf_page_address_fold(b->space,
1301
case BUF_BLOCK_FILE_PAGE:
1302
/* uncompressed page */
1304
case BUF_BLOCK_ZIP_FREE:
1305
case BUF_BLOCK_ZIP_PAGE:
1306
case BUF_BLOCK_NOT_USED:
1307
case BUF_BLOCK_READY_FOR_USE:
1308
case BUF_BLOCK_MEMORY:
1309
case BUF_BLOCK_REMOVE_HASH:
1315
buf_pool_mutex_exit();
1318
/************************************************************************
1319
Resizes the buffer pool. */
1322
buf_pool_resize(void)
1323
/*=================*/
1325
buf_pool_mutex_enter();
1327
if (srv_buf_pool_old_size == srv_buf_pool_size) {
1329
buf_pool_mutex_exit();
813
/* Scan awe_LRU_free_mapped from the end and try to find a block
814
which is not bufferfixed or io-fixed */
816
bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped);
821
mutex_enter(&bck->mutex);
823
skip = (bck->state == BUF_BLOCK_FILE_PAGE
824
&& (bck->buf_fix_count != 0 || bck->io_fix != 0));
827
mutex_exit(&bck->mutex);
829
/* We have to skip this */
830
bck = UT_LIST_GET_PREV(awe_LRU_free_mapped, bck);
1333
if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
1335
buf_pool_mutex_exit();
1337
/* Disable adaptive hash indexes and empty the index
1338
in order to free up memory in the buffer pool chunks. */
1339
buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
1341
} else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
1343
/* Enlarge the buffer pool by at least one megabyte */
1346
= srv_buf_pool_size - srv_buf_pool_curr_size;
1347
buf_chunk_t* chunks;
1350
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1352
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
1355
chunk = &chunks[buf_pool->n_chunks];
1357
if (!buf_chunk_init(chunk, mem_size)) {
832
/* We can map block to the frame of bck */
834
os_awe_map_physical_mem_to_window(
836
UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE,
839
block->frame = bck->frame;
841
*(buf_pool->blocks_of_frames
842
+ (((ulint)(block->frame
843
- buf_pool->frame_zero))
844
>> UNIV_PAGE_SIZE_SHIFT))
848
UT_LIST_REMOVE(awe_LRU_free_mapped,
849
buf_pool->awe_LRU_free_mapped,
852
if (add_to_mapped_list) {
855
buf_pool->awe_LRU_free_mapped,
859
buf_pool->n_pages_awe_remapped++;
861
mutex_exit(&bck->mutex);
1360
buf_pool->curr_size += chunk->size;
1361
srv_buf_pool_curr_size = buf_pool->curr_size
1363
mem_free(buf_pool->chunks);
1364
buf_pool->chunks = chunks;
1365
buf_pool->n_chunks++;
1368
srv_buf_pool_old_size = srv_buf_pool_size;
1369
buf_pool_mutex_exit();
868
"InnoDB: AWE: Fatal error: cannot find a page to unmap\n"
869
"InnoDB: awe_LRU_free_mapped list length %lu\n",
870
(ulong) UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
875
/************************************************************************
876
Allocates a buffer block. */
879
buf_block_alloc(void)
880
/*=================*/
881
/* out, own: the allocated block; also if AWE
882
is used it is guaranteed that the page is
887
block = buf_LRU_get_free_block();
1372
buf_pool_page_hash_rebuild();
892
1375
/************************************************************************
1114
1505
This function should be called when we free a file page and want the
1115
1506
debug version to check that it is not accessed any more unless
1116
1507
reallocated. */
1119
1510
buf_page_reset_file_page_was_freed(
1120
1511
/*===============================*/
1121
/* out: control block if found from page hash table,
1512
/* out: control block if found in page hash table,
1122
1513
otherwise NULL */
1123
1514
ulint space, /* in: space id */
1124
1515
ulint offset) /* in: page number */
1128
mutex_enter_fast(&(buf_pool->mutex));
1130
block = buf_page_hash_get(space, offset);
1133
block->file_page_was_freed = FALSE;
1136
mutex_exit(&(buf_pool->mutex));
1519
buf_pool_mutex_enter();
1521
bpage = buf_page_hash_get(space, offset);
1524
bpage->file_page_was_freed = FALSE;
1527
buf_pool_mutex_exit();
1531
#endif /* UNIV_DEBUG_FILE_ACCESSES */
1533
/************************************************************************
1534
Get read access to a compressed page (usually of type
1535
FIL_PAGE_TYPE_ZBLOB or FIL_PAGE_TYPE_ZBLOB2).
1536
The page must be released with buf_page_release_zip().
1537
NOTE: the page is not protected by any latch. Mutual exclusion has to
1538
be implemented at a higher level. In other words, all possible
1539
accesses to a given page through this function must be protected by
1540
the same set of mutexes or latches. */
1545
/* out: pointer to the block */
1546
ulint space, /* in: space id */
1547
ulint zip_size,/* in: compressed page size */
1548
ulint offset) /* in: page number */
1551
mutex_t* block_mutex;
1554
#ifndef UNIV_LOG_DEBUG
1555
ut_ad(!ibuf_inside());
1557
buf_pool->n_page_gets++;
1560
buf_pool_mutex_enter();
1562
bpage = buf_page_hash_get(space, offset);
1567
/* Page not in buf_pool: needs to be read from file */
1569
buf_pool_mutex_exit();
1571
buf_read_page(space, zip_size, offset);
1573
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1574
ut_a(++buf_dbg_counter % 37 || buf_validate());
1575
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1578
if (UNIV_UNLIKELY(!bpage->zip.data)) {
1579
/* There is no compressed page. */
1580
buf_pool_mutex_exit();
1584
block_mutex = buf_page_get_mutex(bpage);
1585
mutex_enter(block_mutex);
1587
switch (buf_page_get_state(bpage)) {
1588
case BUF_BLOCK_NOT_USED:
1589
case BUF_BLOCK_READY_FOR_USE:
1590
case BUF_BLOCK_MEMORY:
1591
case BUF_BLOCK_REMOVE_HASH:
1592
case BUF_BLOCK_ZIP_FREE:
1595
case BUF_BLOCK_ZIP_PAGE:
1596
case BUF_BLOCK_ZIP_DIRTY:
1597
bpage->buf_fix_count++;
1599
case BUF_BLOCK_FILE_PAGE:
1600
/* Discard the uncompressed page frame if possible. */
1601
if (buf_LRU_free_block(bpage, FALSE, NULL)
1604
mutex_exit(block_mutex);
1608
buf_block_buf_fix_inc((buf_block_t*) bpage,
1609
__FILE__, __LINE__);
1613
must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
1615
buf_pool_mutex_exit();
1617
buf_page_set_accessed(bpage, TRUE);
1619
mutex_exit(block_mutex);
1621
buf_block_make_young(bpage);
1623
#ifdef UNIV_DEBUG_FILE_ACCESSES
1624
ut_a(!bpage->file_page_was_freed);
1627
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1628
ut_a(++buf_dbg_counter % 5771 || buf_validate());
1629
ut_a(bpage->buf_fix_count > 0);
1630
ut_a(buf_page_in_file(bpage));
1631
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1634
/* Let us wait until the read operation
1638
enum buf_io_fix io_fix;
1640
mutex_enter(block_mutex);
1641
io_fix = buf_page_get_io_fix(bpage);
1642
mutex_exit(block_mutex);
1644
if (io_fix == BUF_IO_READ) {
1646
os_thread_sleep(WAIT_FOR_READ);
1653
#ifdef UNIV_IBUF_COUNT_DEBUG
1654
ut_a(ibuf_count_get(buf_page_get_space(bpage),
1655
buf_page_get_page_no(bpage)) == 0);
1660
/************************************************************************
1661
Initialize some fields of a control block. */
1666
buf_block_t* block) /* in: block to init */
1668
block->check_index_page_at_flush = FALSE;
1669
block->index = NULL;
1671
block->n_hash_helps = 0;
1672
block->is_hashed = FALSE;
1673
block->n_fields = 1;
1675
block->left_side = TRUE;
1678
/************************************************************************
1679
Decompress a block. */
1684
/* out: TRUE if successful */
1685
buf_block_t* block, /* in/out: block */
1686
ibool check) /* in: TRUE=verify the page checksum */
1688
const byte* frame = block->page.zip.data;
1690
ut_ad(buf_block_get_zip_size(block));
1691
ut_a(buf_block_get_space(block) != 0);
1693
if (UNIV_LIKELY(check)) {
1694
ulint stamp_checksum = mach_read_from_4(
1695
frame + FIL_PAGE_SPACE_OR_CHKSUM);
1696
ulint calc_checksum = page_zip_calc_checksum(
1697
frame, page_zip_get_size(&block->page.zip));
1699
if (UNIV_UNLIKELY(stamp_checksum != calc_checksum)) {
1700
ut_print_timestamp(stderr);
1702
" InnoDB: compressed page checksum mismatch"
1703
" (space %u page %u): %lu != %lu\n",
1704
block->page.space, block->page.offset,
1705
stamp_checksum, calc_checksum);
1710
switch (fil_page_get_type(frame)) {
1711
case FIL_PAGE_INDEX:
1712
if (page_zip_decompress(&block->page.zip,
1718
"InnoDB: unable to decompress space %lu page %lu\n",
1719
(ulong) block->page.space,
1720
(ulong) block->page.offset);
1723
case FIL_PAGE_TYPE_ALLOCATED:
1724
case FIL_PAGE_INODE:
1725
case FIL_PAGE_IBUF_BITMAP:
1726
case FIL_PAGE_TYPE_FSP_HDR:
1727
case FIL_PAGE_TYPE_XDES:
1728
case FIL_PAGE_TYPE_ZBLOB:
1729
case FIL_PAGE_TYPE_ZBLOB2:
1730
/* Copy to uncompressed storage. */
1731
memcpy(block->frame, frame,
1732
buf_block_get_zip_size(block));
1736
ut_print_timestamp(stderr);
1738
" InnoDB: unknown compressed page"
1740
fil_page_get_type(frame));
1744
/************************************************************************
1745
Find out if a buffer block was created by buf_chunk_init(). */
1748
buf_block_is_uncompressed(
1749
/*======================*/
1750
/* out: TRUE if "block" has
1751
been added to buf_pool->free
1752
by buf_chunk_init() */
1753
const buf_block_t* block) /* in: pointer to block,
1756
const buf_chunk_t* chunk = buf_pool->chunks;
1757
const buf_chunk_t* const echunk = chunk + buf_pool->n_chunks;
1759
ut_ad(buf_pool_mutex_own());
1761
if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
1762
/* The pointer should be aligned. */
1766
while (chunk < echunk) {
1767
if (block >= chunk->blocks
1768
&& block < chunk->blocks + chunk->size) {
1141
1779
/************************************************************************
1142
1780
This is the general function used to get access to a database page. */
1145
1783
buf_page_get_gen(
1146
1784
/*=============*/
1147
/* out: pointer to the frame or NULL */
1785
/* out: pointer to the block or NULL */
1148
1786
ulint space, /* in: space id */
1787
ulint zip_size,/* in: compressed page size in bytes
1788
or 0 for uncompressed pages */
1149
1789
ulint offset, /* in: page number */
1150
1790
ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
1151
buf_frame_t* guess, /* in: guessed frame or NULL */
1791
buf_block_t* guess, /* in: guessed block or NULL */
1152
1792
ulint mode, /* in: BUF_GET, BUF_GET_IF_IN_POOL,
1153
1793
BUF_GET_NO_LATCH, BUF_GET_NOWAIT */
1154
1794
const char* file, /* in: file name */
1168
1807
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
1169
1808
ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
1170
1809
|| (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));
1810
ut_ad(zip_size == fil_space_get_zip_size(space));
1171
1811
#ifndef UNIV_LOG_DEBUG
1172
ut_ad(!ibuf_inside() || ibuf_page(space, offset));
1812
ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset));
1174
1814
buf_pool->n_page_gets++;
1177
mutex_enter_fast(&(buf_pool->mutex));
1180
block = buf_block_align(guess);
1182
if ((offset != block->offset) || (space != block->space)
1183
|| (block->state != BUF_BLOCK_FILE_PAGE)) {
1817
buf_pool_mutex_enter();
1820
/* If the guess is a compressed page descriptor that
1821
has been allocated by buf_buddy_alloc(), it may have
1822
been invalidated by buf_buddy_relocate(). In that
1823
case, block could point to something that happens to
1824
contain the expected bits in block->page. Similarly,
1825
the guess may be pointing to a buffer pool chunk that
1826
has been released when resizing the buffer pool. */
1828
if (!buf_block_is_uncompressed(block)
1829
|| offset != block->page.offset
1830
|| space != block->page.space
1831
|| buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
1833
block = guess = NULL;
1835
ut_ad(!block->page.in_zip_hash);
1836
ut_ad(block->page.in_page_hash);
1189
1840
if (block == NULL) {
1190
block = buf_page_hash_get(space, offset);
1841
block = (buf_block_t*) buf_page_hash_get(space, offset);
1193
1845
if (block == NULL) {
1194
1846
/* Page not in buf_pool: needs to be read from file */
1196
mutex_exit(&(buf_pool->mutex));
1848
buf_pool_mutex_exit();
1198
1850
if (mode == BUF_GET_IF_IN_POOL) {
1203
buf_read_page(space, offset);
1208
if (buf_dbg_counter % 37 == 0) {
1209
ut_ad(buf_validate());
1855
buf_read_page(space, zip_size, offset);
1857
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
1858
ut_a(++buf_dbg_counter % 37 || buf_validate());
1859
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1215
mutex_enter(&block->mutex);
1217
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
1221
if (block->io_fix == BUF_IO_READ) {
1225
if (mode == BUF_GET_IF_IN_POOL) {
1226
/* The page is only being read to buffer */
1227
mutex_exit(&buf_pool->mutex);
1863
ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
1865
must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
1867
if (must_read && mode == BUF_GET_IF_IN_POOL) {
1868
/* The page is only being read to buffer */
1869
buf_pool_mutex_exit();
1874
switch (buf_block_get_state(block)) {
1878
case BUF_BLOCK_FILE_PAGE:
1881
case BUF_BLOCK_ZIP_PAGE:
1882
case BUF_BLOCK_ZIP_DIRTY:
1883
bpage = &block->page;
1885
if (bpage->buf_fix_count
1886
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
1887
/* This condition often occurs when the buffer
1888
is not buffer-fixed, but I/O-fixed by
1889
buf_page_init_for_read(). */
1891
/* The block is buffer-fixed or I/O-fixed.
1893
buf_pool_mutex_exit();
1894
os_thread_sleep(WAIT_FOR_READ);
1899
/* Allocate an uncompressed page. */
1900
buf_pool_mutex_exit();
1902
block = buf_LRU_get_free_block(0);
1905
buf_pool_mutex_enter();
1906
mutex_enter(&block->mutex);
1909
buf_page_t* hash_bpage
1910
= buf_page_hash_get(space, offset);
1912
if (UNIV_UNLIKELY(bpage != hash_bpage)) {
1913
/* The buf_pool->page_hash was modified
1914
while buf_pool_mutex was released.
1915
Free the block that was allocated. */
1917
buf_LRU_block_free_non_file_page(block);
1918
mutex_exit(&block->mutex);
1920
block = (buf_block_t*) hash_bpage;
1926
(bpage->buf_fix_count
1927
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
1929
/* The block was buffer-fixed or I/O-fixed
1930
while buf_pool_mutex was not held by this thread.
1931
Free the block that was allocated and try again.
1932
This should be extremely unlikely. */
1934
buf_LRU_block_free_non_file_page(block);
1228
1935
mutex_exit(&block->mutex);
1937
goto wait_until_unfixed;
1940
/* Move the compressed page from bpage to block,
1941
and uncompress it. */
1943
mutex_enter(&buf_pool_zip_mutex);
1945
buf_relocate(bpage, &block->page);
1946
buf_block_init_low(block);
1947
block->lock_hash_val = lock_rec_hash(space, offset);
1949
UNIV_MEM_DESC(&block->page.zip.data,
1950
page_zip_get_size(&block->page.zip), block);
1952
if (buf_page_get_state(&block->page)
1953
== BUF_BLOCK_ZIP_PAGE) {
1954
UT_LIST_REMOVE(list, buf_pool->zip_clean,
1956
ut_ad(!block->page.in_flush_list);
1958
/* Relocate buf_pool->flush_list. */
1961
b = UT_LIST_GET_PREV(list, &block->page);
1962
ut_ad(block->page.in_flush_list);
1963
UT_LIST_REMOVE(list, buf_pool->flush_list,
1967
UT_LIST_INSERT_AFTER(
1968
list, buf_pool->flush_list, b,
1972
list, buf_pool->flush_list,
1977
/* Buffer-fix, I/O-fix, and X-latch the block
1978
for the duration of the decompression.
1979
Also add the block to the unzip_LRU list. */
1980
block->page.state = BUF_BLOCK_FILE_PAGE;
1982
/* Insert at the front of unzip_LRU list */
1983
buf_unzip_LRU_add_block(block, FALSE);
1985
block->page.buf_fix_count = 1;
1986
buf_block_set_io_fix(block, BUF_IO_READ);
1987
buf_pool->n_pend_unzip++;
1988
rw_lock_x_lock(&block->lock);
1989
mutex_exit(&block->mutex);
1990
mutex_exit(&buf_pool_zip_mutex);
1992
buf_buddy_free(bpage, sizeof *bpage);
1994
buf_pool_mutex_exit();
1996
/* Decompress the page and apply buffered operations
1997
while not holding buf_pool_mutex or block->mutex. */
1998
success = buf_zip_decompress(block, srv_use_checksums);
2000
if (UNIV_LIKELY(success)) {
2001
ibuf_merge_or_delete_for_page(block, space, offset,
2005
/* Unfix and unlatch the block. */
2006
buf_pool_mutex_enter();
2007
mutex_enter(&block->mutex);
2008
buf_pool->n_pend_unzip--;
2009
block->page.buf_fix_count--;
2010
buf_block_set_io_fix(block, BUF_IO_NONE);
2011
mutex_exit(&block->mutex);
2012
rw_lock_x_unlock(&block->lock);
2014
if (UNIV_UNLIKELY(!success)) {
2016
buf_pool_mutex_exit();
1234
/* If AWE is enabled and the page is not mapped to a frame, then
1237
if (block->frame == NULL) {
1240
/* We set second parameter TRUE because the block is in the
1241
LRU list and we must put it to awe_LRU_free_mapped list once
1242
mapped to a frame */
1244
buf_awe_map_page_to_frame(block, TRUE);
1247
#ifdef UNIV_SYNC_DEBUG
1248
buf_block_buf_fix_inc_debug(block, file, line);
1250
buf_block_buf_fix_inc(block);
1252
mutex_exit(&buf_pool->mutex);
2022
case BUF_BLOCK_ZIP_FREE:
2023
case BUF_BLOCK_NOT_USED:
2024
case BUF_BLOCK_READY_FOR_USE:
2025
case BUF_BLOCK_MEMORY:
2026
case BUF_BLOCK_REMOVE_HASH:
2031
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2033
mutex_enter(&block->mutex);
2034
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
2036
buf_block_buf_fix_inc(block, file, line);
2037
buf_pool_mutex_exit();
1254
2039
/* Check if this is the first access to the page */
1256
accessed = block->accessed;
2041
accessed = buf_page_is_accessed(&block->page);
1258
block->accessed = TRUE;
2043
buf_page_set_accessed(&block->page, TRUE);
1260
2045
mutex_exit(&block->mutex);
1262
buf_block_make_young(block);
2047
buf_block_make_young(&block->page);
1264
2049
#ifdef UNIV_DEBUG_FILE_ACCESSES
1265
ut_a(block->file_page_was_freed == FALSE);
1271
if (buf_dbg_counter % 5771 == 0) {
1272
ut_ad(buf_validate());
1275
ut_ad(block->buf_fix_count > 0);
1276
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
2050
ut_a(!block->page.file_page_was_freed);
2053
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2054
ut_a(++buf_dbg_counter % 5771 || buf_validate());
2055
ut_a(block->page.buf_fix_count > 0);
2056
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2057
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1278
2059
if (mode == BUF_GET_NOWAIT) {
1279
2062
if (rw_latch == RW_S_LATCH) {
1280
2063
success = rw_lock_s_lock_func_nowait(&(block->lock),
1546
2300
if (!success) {
1547
2301
mutex_enter(&block->mutex);
1549
block->buf_fix_count--;
2302
buf_block_buf_fix_dec(block);
1551
2303
mutex_exit(&block->mutex);
1553
#ifdef UNIV_SYNC_DEBUG
1554
rw_lock_s_unlock(&(block->debug_latch));
1560
2308
mtr_memo_push(mtr, block, fix_type);
1565
if (buf_dbg_counter % 5771 == 0) {
1566
ut_ad(buf_validate());
1569
ut_ad(block->buf_fix_count > 0);
1570
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
2310
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2311
ut_a(++buf_dbg_counter % 5771 || buf_validate());
2312
ut_a(block->page.buf_fix_count > 0);
2313
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2314
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
1571
2315
#ifdef UNIV_DEBUG_FILE_ACCESSES
1572
ut_a(block->file_page_was_freed == FALSE);
2316
ut_a(block->page.file_page_was_freed == FALSE);
1575
#ifdef UNIV_IBUF_DEBUG
2319
#ifdef UNIV_IBUF_COUNT_DEBUG
1576
2320
ut_a((mode == BUF_KEEP_OLD)
1577
|| (ibuf_count_get(block->space, block->offset) == 0));
2321
|| (ibuf_count_get(buf_block_get_space(block),
2322
buf_block_get_page_no(block)) == 0));
1579
2324
buf_pool->n_page_gets++;
2329
/***********************************************************************
2330
Given a tablespace id and page number tries to get that page. If the
2331
page is not in the buffer pool it is not loaded and NULL is returned.
2332
Suitable for using when holding the kernel mutex. */
2335
buf_page_try_get_func(
2336
/*==================*/
2337
/* out: pointer to a page or NULL */
2338
ulint space_id,/* in: tablespace id */
2339
ulint page_no,/* in: page number */
2340
const char* file, /* in: file name */
2341
ulint line, /* in: line where called */
2342
mtr_t* mtr) /* in: mini-transaction */
2348
buf_pool_mutex_enter();
2349
block = buf_block_hash_get(space_id, page_no);
2352
buf_pool_mutex_exit();
2356
mutex_enter(&block->mutex);
2357
buf_pool_mutex_exit();
2359
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2360
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2361
ut_a(buf_block_get_space(block) == space_id);
2362
ut_a(buf_block_get_page_no(block) == page_no);
2363
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
2365
buf_block_buf_fix_inc(block, file, line);
2366
mutex_exit(&block->mutex);
2368
fix_type = MTR_MEMO_PAGE_S_FIX;
2369
success = rw_lock_s_lock_func_nowait(&block->lock, file, line);
2372
/* Let us try to get an X-latch. If the current thread
2373
is holding an X-latch on the page, we cannot get an
2376
fix_type = MTR_MEMO_PAGE_X_FIX;
2377
success = rw_lock_x_lock_func_nowait(&block->lock,
2382
mutex_enter(&block->mutex);
2383
buf_block_buf_fix_dec(block);
2384
mutex_exit(&block->mutex);
2389
mtr_memo_push(mtr, block, fix_type);
2390
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2391
ut_a(++buf_dbg_counter % 5771 || buf_validate());
2392
ut_a(block->page.buf_fix_count > 0);
2393
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2394
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
2395
#ifdef UNIV_DEBUG_FILE_ACCESSES
2396
ut_a(block->page.file_page_was_freed == FALSE);
2397
#endif /* UNIV_DEBUG_FILE_ACCESSES */
2398
#ifdef UNIV_SYNC_DEBUG
2399
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
2400
#endif /* UNIV_SYNC_DEBUG */
2401
buf_pool->n_page_gets++;
2406
/************************************************************************
2407
Initialize some fields of a control block. */
2412
buf_page_t* bpage) /* in: block to init */
2414
bpage->flush_type = BUF_FLUSH_LRU;
2415
bpage->accessed = FALSE;
2416
bpage->io_fix = BUF_IO_NONE;
2417
bpage->buf_fix_count = 0;
2418
bpage->freed_page_clock = 0;
2419
bpage->newest_modification = 0;
2420
bpage->oldest_modification = 0;
2421
HASH_INVALIDATE(bpage, hash);
2422
#ifdef UNIV_DEBUG_FILE_ACCESSES
2423
bpage->file_page_was_freed = FALSE;
2424
#endif /* UNIV_DEBUG_FILE_ACCESSES */
2427
#ifdef UNIV_HOTBACKUP
1584
2428
/************************************************************************
1585
2429
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
1588
2432
buf_page_init_for_backup_restore(
1589
2433
/*=============================*/
1590
2434
ulint space, /* in: space id */
1591
2435
ulint offset, /* in: offset of the page within space
1592
2436
in units of a page */
2437
ulint zip_size,/* in: compressed page size in bytes
2438
or 0 for uncompressed pages */
1593
2439
buf_block_t* block) /* in: block to init */
1595
/* Set the state of the block */
1596
block->magic_n = BUF_BLOCK_MAGIC_N;
1598
block->state = BUF_BLOCK_FILE_PAGE;
1599
block->space = space;
1600
block->offset = offset;
2441
buf_block_init_low(block);
1602
2443
block->lock_hash_val = 0;
1604
block->freed_page_clock = 0;
1606
block->newest_modification = ut_dulint_zero;
1607
block->oldest_modification = ut_dulint_zero;
1609
block->accessed = FALSE;
1610
block->buf_fix_count = 0;
1613
block->n_hash_helps = 0;
1614
block->is_hashed = FALSE;
1615
block->n_fields = 1;
1617
block->left_side = TRUE;
1619
block->file_page_was_freed = FALSE;
2445
buf_page_init_low(&block->page);
2446
block->page.state = BUF_BLOCK_FILE_PAGE;
2447
block->page.space = space;
2448
block->page.offset = offset;
2450
page_zip_des_init(&block->page.zip);
2452
/* We assume that block->page.data has been allocated
2453
with zip_size == UNIV_PAGE_SIZE. */
2454
ut_ad(zip_size <= UNIV_PAGE_SIZE);
2455
ut_ad(ut_is_2pow(zip_size));
2456
page_zip_set_size(&block->page.zip, zip_size);
2458
#endif /* UNIV_HOTBACKUP */
1622
2460
/************************************************************************
1623
2461
Inits a page to the buffer buf_pool. */
1743
2573
ut_ad(mode == BUF_READ_ANY_PAGE);
1746
block = buf_block_alloc();
1750
mutex_enter(&(buf_pool->mutex));
1751
mutex_enter(&block->mutex);
2576
if (zip_size && UNIV_LIKELY(!unzip)
2577
&& UNIV_LIKELY(!recv_recovery_is_on())) {
2580
block = buf_LRU_get_free_block(0);
2584
buf_pool_mutex_enter();
2586
if (buf_page_hash_get(space, offset)) {
2587
/* The page is already in the buffer pool. */
2590
mutex_enter(&block->mutex);
2591
buf_LRU_block_free_non_file_page(block);
2592
mutex_exit(&block->mutex);
2596
buf_pool_mutex_exit();
2598
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
1753
2606
if (fil_tablespace_deleted_or_being_deleted_in_mem(
1754
2607
space, tablespace_version)) {
2608
/* The page belongs to a space which has been
2609
deleted or is being deleted. */
1755
2610
*err = DB_TABLESPACE_DELETED;
1758
if (*err == DB_TABLESPACE_DELETED
1759
|| NULL != buf_page_hash_get(space, offset)) {
1761
/* The page belongs to a space which has been
1762
deleted or is being deleted, or the page is
1763
already in buf_pool, return */
2616
bpage = &block->page;
2617
mutex_enter(&block->mutex);
2618
buf_page_init(space, offset, block);
2620
/* The block must be put to the LRU list, to the old blocks */
2621
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2623
/* We set a pass-type x-lock on the frame because then
2624
the same thread which called for the read operation
2625
(and is running now at this point of code) can wait
2626
for the read to complete by waiting for the x-lock on
2627
the frame; if the x-lock were recursive, the same
2628
thread would illegally get the x-lock before the page
2629
read is completed. The x-lock is cleared by the
2630
io-handler thread. */
2632
rw_lock_x_lock_gen(&block->lock, BUF_IO_READ);
2633
buf_page_set_io_fix(bpage, BUF_IO_READ);
2635
if (UNIV_UNLIKELY(zip_size)) {
2636
page_zip_set_size(&block->page.zip, zip_size);
2638
/* buf_pool_mutex may be released and
2639
reacquired by buf_buddy_alloc(). Thus, we
2640
must release block->mutex in order not to
2641
break the latching order in the reacquisition
2642
of buf_pool_mutex. We also must defer this
2643
operation until after the block descriptor has
2644
been added to buf_pool->LRU and
2645
buf_pool->page_hash. */
2646
mutex_exit(&block->mutex);
2647
data = buf_buddy_alloc(zip_size, &lru);
2648
mutex_enter(&block->mutex);
2649
block->page.zip.data = data;
2651
/* To maintain the invariant
2652
block->in_unzip_LRU_list
2653
== buf_page_belongs_to_unzip_LRU(&block->page)
2654
we have to add this block to unzip_LRU
2655
after block->page.zip.data is set. */
2656
ut_ad(buf_page_belongs_to_unzip_LRU(&block->page));
2657
buf_unzip_LRU_add_block(block, TRUE);
1765
2660
mutex_exit(&block->mutex);
1766
mutex_exit(&(buf_pool->mutex));
1768
buf_block_free(block);
1770
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
2662
/* Defer buf_buddy_alloc() until after the block has
2663
been found not to exist. The buf_buddy_alloc() and
2664
buf_buddy_free() calls may be expensive because of
2665
buf_buddy_relocate(). */
2667
/* The compressed page must be allocated before the
2668
control block (bpage), in order to avoid the
2669
invocation of buf_buddy_relocate_block() on
2670
uninitialized data. */
2671
data = buf_buddy_alloc(zip_size, &lru);
2672
bpage = buf_buddy_alloc(sizeof *bpage, &lru);
2674
/* If buf_buddy_alloc() allocated storage from the LRU list,
2675
it released and reacquired buf_pool_mutex. Thus, we must
2676
check the page_hash again, as it may have been modified. */
2677
if (UNIV_UNLIKELY(lru)
2678
&& UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
2680
/* The block was added by some other thread. */
2681
buf_buddy_free(bpage, sizeof *bpage);
2682
buf_buddy_free(data, zip_size);
2686
page_zip_des_init(&bpage->zip);
2687
page_zip_set_size(&bpage->zip, zip_size);
2688
bpage->zip.data = data;
2690
mutex_enter(&buf_pool_zip_mutex);
2691
UNIV_MEM_DESC(bpage->zip.data,
2692
page_zip_get_size(&bpage->zip), bpage);
2693
buf_page_init_low(bpage);
2694
bpage->state = BUF_BLOCK_ZIP_PAGE;
2695
bpage->space = space;
2696
bpage->offset = offset;
2699
bpage->in_page_hash = FALSE;
2700
bpage->in_zip_hash = FALSE;
2701
bpage->in_flush_list = FALSE;
2702
bpage->in_free_list = FALSE;
2703
bpage->in_LRU_list = FALSE;
2704
#endif /* UNIV_DEBUG */
2706
ut_d(bpage->in_page_hash = TRUE);
2707
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2708
buf_page_address_fold(space, offset), bpage);
2710
/* The block must be put to the LRU list, to the old blocks */
2711
buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2712
buf_LRU_insert_zip_clean(bpage);
2714
buf_page_set_io_fix(bpage, BUF_IO_READ);
2716
mutex_exit(&buf_pool_zip_mutex);
1780
buf_page_init(space, offset, block);
1782
/* The block must be put to the LRU list, to the old blocks */
1784
buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */
1786
block->io_fix = BUF_IO_READ;
1788
2719
buf_pool->n_pend_reads++;
1790
/* We set a pass-type x-lock on the frame because then the same
1791
thread which called for the read operation (and is running now at
1792
this point of code) can wait for the read to complete by waiting
1793
for the x-lock on the frame; if the x-lock were recursive, the
1794
same thread would illegally get the x-lock before the page read
1795
is completed. The x-lock is cleared by the io-handler thread. */
1797
rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ);
1799
mutex_exit(&block->mutex);
1800
mutex_exit(&(buf_pool->mutex));
2720
buf_pool_mutex_exit();
1802
2722
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
1804
2724
mtr_commit(&mtr);
2727
ut_ad(buf_page_in_file(bpage));
1810
2731
/************************************************************************
1811
2732
Initializes a page to the buffer buf_pool. The page is usually not read
1812
2733
from a file even if it cannot be found in the buffer buf_pool. This is one
1813
2734
of the functions which perform to a block a state transition NOT_USED =>
1814
FILE_PAGE (the other is buf_page_init_for_read above). */
2735
FILE_PAGE (the other is buf_page_get_gen). */
1817
2738
buf_page_create(
1818
2739
/*============*/
1819
/* out: pointer to the frame, page bufferfixed */
2740
/* out: pointer to the block, page bufferfixed */
1820
2741
ulint space, /* in: space id */
1821
2742
ulint offset, /* in: offset of the page within space in units of
2744
ulint zip_size,/* in: compressed page size, or 0 */
1823
2745
mtr_t* mtr) /* in: mini-transaction handle */
1825
2747
buf_frame_t* frame;