675
555
/************************************************************************
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
/************************************************************************
912
556
Creates the buffer pool. */
917
561
/* out, own: buf_pool object, NULL if not
918
562
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
923
buf_pool = mem_zalloc(sizeof(buf_pool_t));
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));
925
595
/* 1. Initialize general fields
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);
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;
951
711
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;
953
725
/* 2. Initialize flushing fields
954
-------------------------------- */
726
---------------------------- */
727
UT_LIST_INIT(buf_pool->flush_list);
956
for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
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;
957
732
buf_pool->no_flush[i] = os_event_create(NULL);
735
buf_pool->LRU_flush_ended = 0;
960
737
buf_pool->ulint_clock = 1;
738
buf_pool->freed_page_clock = 0;
962
740
/* 3. Initialize LRU fields
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(). */
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);
974
786
return(buf_pool);
977
789
/************************************************************************
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();
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)));
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)) {
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);
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++;
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);
1368
srv_buf_pool_old_size = srv_buf_pool_size;
1369
buf_pool_mutex_exit();
1372
buf_pool_page_hash_rebuild();
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();
1375
892
/************************************************************************
1505
1114
This function should be called when we free a file page and want the
1506
1115
debug version to check that it is not accessed any more unless
1507
1116
reallocated. */
1510
1119
buf_page_reset_file_page_was_freed(
1511
1120
/*===============================*/
1512
/* out: control block if found in page hash table,
1121
/* out: control block if found from page hash table,
1513
1122
otherwise NULL */
1514
1123
ulint space, /* in: space id */
1515
1124
ulint offset) /* in: page number */
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) {
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));
1779
1141
/************************************************************************
1780
1142
This is the general function used to get access to a database page. */
1783
1145
buf_page_get_gen(
1784
1146
/*=============*/
1785
/* out: pointer to the block or NULL */
1147
/* out: pointer to the frame or NULL */
1786
1148
ulint space, /* in: space id */
1787
ulint zip_size,/* in: compressed page size in bytes
1788
or 0 for uncompressed pages */
1789
1149
ulint offset, /* in: page number */
1790
1150
ulint rw_latch,/* in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
1791
buf_block_t* guess, /* in: guessed block or NULL */
1151
buf_frame_t* guess, /* in: guessed frame or NULL */
1792
1152
ulint mode, /* in: BUF_GET, BUF_GET_IF_IN_POOL,
1793
1153
BUF_GET_NO_LATCH, BUF_GET_NOWAIT */
1794
1154
const char* file, /* in: file name */
1807
1168
ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
1808
1169
ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
1809
1170
|| (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));
1810
ut_ad(zip_size == fil_space_get_zip_size(space));
1811
1171
#ifndef UNIV_LOG_DEBUG
1812
ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset));
1172
ut_ad(!ibuf_inside() || ibuf_page(space, offset));
1814
1174
buf_pool->n_page_gets++;
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);
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)) {
1840
1189
if (block == NULL) {
1841
block = (buf_block_t*) buf_page_hash_get(space, offset);
1190
block = buf_page_hash_get(space, offset);
1845
1193
if (block == NULL) {
1846
1194
/* Page not in buf_pool: needs to be read from file */
1848
buf_pool_mutex_exit();
1196
mutex_exit(&(buf_pool->mutex));
1850
1198
if (mode == BUF_GET_IF_IN_POOL) {
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 */
1203
buf_read_page(space, offset);
1208
if (buf_dbg_counter % 37 == 0) {
1209
ut_ad(buf_validate());
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);
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);
1935
1228
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();
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();
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);
2039
1254
/* Check if this is the first access to the page */
2041
accessed = buf_page_is_accessed(&block->page);
1256
accessed = block->accessed;
2043
buf_page_set_accessed(&block->page, TRUE);
1258
block->accessed = TRUE;
2045
1260
mutex_exit(&block->mutex);
2047
buf_block_make_young(&block->page);
1262
buf_block_make_young(block);
2049
1264
#ifdef UNIV_DEBUG_FILE_ACCESSES
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 */
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);
2059
1278
if (mode == BUF_GET_NOWAIT) {
2062
1279
if (rw_latch == RW_S_LATCH) {
2063
1280
success = rw_lock_s_lock_func_nowait(&(block->lock),
2300
1546
if (!success) {
2301
1547
mutex_enter(&block->mutex);
2302
buf_block_buf_fix_dec(block);
1549
block->buf_fix_count--;
2303
1551
mutex_exit(&block->mutex);
1553
#ifdef UNIV_SYNC_DEBUG
1554
rw_lock_s_unlock(&(block->debug_latch));
2308
1560
mtr_memo_push(mtr, block, fix_type);
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 */
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);
2315
1571
#ifdef UNIV_DEBUG_FILE_ACCESSES
2316
ut_a(block->page.file_page_was_freed == FALSE);
1572
ut_a(block->file_page_was_freed == FALSE);
2319
#ifdef UNIV_IBUF_COUNT_DEBUG
1575
#ifdef UNIV_IBUF_DEBUG
2320
1576
ut_a((mode == BUF_KEEP_OLD)
2321
|| (ibuf_count_get(buf_block_get_space(block),
2322
buf_block_get_page_no(block)) == 0));
1577
|| (ibuf_count_get(block->space, block->offset) == 0));
2324
1579
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
2428
1584
/************************************************************************
2429
1585
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
2432
1588
buf_page_init_for_backup_restore(
2433
1589
/*=============================*/
2434
1590
ulint space, /* in: space id */
2435
1591
ulint offset, /* in: offset of the page within space
2436
1592
in units of a page */
2437
ulint zip_size,/* in: compressed page size in bytes
2438
or 0 for uncompressed pages */
2439
1593
buf_block_t* block) /* in: block to init */
2441
buf_block_init_low(block);
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;
2443
1602
block->lock_hash_val = 0;
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);
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;
2458
#endif /* UNIV_HOTBACKUP */
2460
1622
/************************************************************************
2461
1623
Inits a page to the buffer buf_pool. */
2573
1743
ut_ad(mode == BUF_READ_ANY_PAGE);
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) {
1746
block = buf_block_alloc();
1750
mutex_enter(&(buf_pool->mutex));
1751
mutex_enter(&block->mutex);
2606
1753
if (fil_tablespace_deleted_or_being_deleted_in_mem(
2607
1754
space, tablespace_version)) {
1755
*err = DB_TABLESPACE_DELETED;
1758
if (*err == DB_TABLESPACE_DELETED
1759
|| NULL != buf_page_hash_get(space, offset)) {
2608
1761
/* The page belongs to a space which has been
2609
deleted or is being deleted. */
2610
*err = DB_TABLESPACE_DELETED;
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);
1762
deleted or is being deleted, or the page is
1763
already in buf_pool, return */
2660
1765
mutex_exit(&block->mutex);
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);
1766
mutex_exit(&(buf_pool->mutex));
1768
buf_block_free(block);
1770
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
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;
2719
1788
buf_pool->n_pend_reads++;
2720
buf_pool_mutex_exit();
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));
2722
1802
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
2724
1804
mtr_commit(&mtr);
2727
ut_ad(buf_page_in_file(bpage));
2731
1810
/************************************************************************
2732
1811
Initializes a page to the buffer buf_pool. The page is usually not read
2733
1812
from a file even if it cannot be found in the buffer buf_pool. This is one
2734
1813
of the functions which perform to a block a state transition NOT_USED =>
2735
FILE_PAGE (the other is buf_page_get_gen). */
1814
FILE_PAGE (the other is buf_page_init_for_read above). */
2738
1817
buf_page_create(
2739
1818
/*============*/
2740
/* out: pointer to the block, page bufferfixed */
1819
/* out: pointer to the frame, page bufferfixed */
2741
1820
ulint space, /* in: space id */
2742
1821
ulint offset, /* in: offset of the page within space in units of
2744
ulint zip_size,/* in: compressed page size, or 0 */
2745
1823
mtr_t* mtr) /* in: mini-transaction handle */
2747
1825
buf_frame_t* frame;