~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/buf/buf0buf.c

Merge initial InnoDB+ import.

This was applied by generating a patch between MySQL 5.1.50 InnoDB plugin and
the just-merged innodb+ from mysql-trunk revision-id: vasil.dimov@oracle.com-20100422110752-1zowoqxel5xx3z2e

Then, some manual merge resolving and it worked. This should make it much
easier to merge the rest of InnoDB 1.1 and 1.2 from the mysql tree using
my bzr-reapply script.

This takes us to InnoDB 1.1.1(ish).

Show diffs side-by-side

added added

removed removed

Lines of Context:
84
84
The buffer buf_pool contains a single mutex which protects all the
85
85
control data structures of the buf_pool. The content of a buffer frame is
86
86
protected by a separate read-write lock in its control block, though.
87
 
These locks can be locked and unlocked without owning the buf_pool mutex.
 
87
These locks can be locked and unlocked without owning the buf_pool->mutex.
88
88
The OS events in the buf_pool struct can be waited for without owning the
89
 
buf_pool mutex.
 
89
buf_pool->mutex.
90
90
 
91
 
The buf_pool mutex is a hot-spot in main memory, causing a lot of
 
91
The buf_pool->mutex is a hot-spot in main memory, causing a lot of
92
92
memory bus traffic on multiprocessor systems when processors
93
93
alternately access the mutex. On our Pentium, the mutex is accessed
94
94
maybe every 10 microseconds. We gave up the solution to have mutexes
95
95
for each control block, for instance, because it seemed to be
96
96
complicated.
97
97
 
98
 
A solution to reduce mutex contention of the buf_pool mutex is to
 
98
A solution to reduce mutex contention of the buf_pool->mutex is to
99
99
create a separate mutex for the page hash table. On Pentium,
100
100
accessing the hash table takes 2 microseconds, about half
101
 
of the total buf_pool mutex hold time.
 
101
of the total buf_pool->mutex hold time.
102
102
 
103
103
                Control blocks
104
104
                --------------
153
153
which we can use when we want to artificially age a page in the
154
154
buf_pool. This is used if we know that some page is not needed
155
155
again for some time: we insert the block right after the pointer,
156
 
causing it to be replaced sooner than would noramlly be the case.
 
156
causing it to be replaced sooner than would normally be the case.
157
157
Currently this aging mechanism is used for read-ahead mechanism
158
158
of pages, and it can also be used when there is a scan of a full
159
159
table which cannot fit in the memory. Putting the pages near the
160
 
of the LRU list, we make sure that most of the buf_pool stays in the
161
 
main memory, undisturbed.
 
160
end of the LRU list, we make sure that most of the buf_pool stays
 
161
in the main memory, undisturbed.
162
162
 
163
163
The unzip_LRU list contains a subset of the common LRU list.  The
164
164
blocks on the unzip_LRU list hold a compressed file page and the
172
172
holding file pages that have been modified in the memory
173
173
but not written to disk yet. The block with the oldest modification
174
174
which has not yet been written to disk is at the end of the chain.
 
175
The access to this list is protected by flush_list_mutex.
175
176
 
176
177
The chain of unmodified compressed blocks (buf_pool->zip_clean)
177
178
contains the control blocks (buf_page_t) of those compressed pages
246
247
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
247
248
 
248
249
/** The buffer buf_pool of the database */
249
 
UNIV_INTERN buf_pool_t* buf_pool = NULL;
250
 
 
251
 
/** mutex protecting the buffer pool struct and control blocks, except the
252
 
read-write lock in them */
253
 
UNIV_INTERN mutex_t             buf_pool_mutex;
254
 
/** mutex protecting the control blocks of compressed-only pages
255
 
(of type buf_page_t, not buf_block_t) */
256
 
UNIV_INTERN mutex_t             buf_pool_zip_mutex;
 
250
UNIV_INTERN buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS];
257
251
 
258
252
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
259
253
static ulint    buf_dbg_counter = 0; /*!< This is used to insert validation
260
 
                                        operations in excution in the
 
254
                                        operations in execution in the
261
255
                                        debug version */
262
 
/** Flag to forbid the release of the buffer pool mutex.
263
 
Protected by buf_pool_mutex. */
264
 
UNIV_INTERN ulint               buf_pool_mutex_exit_forbidden = 0;
265
256
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
266
257
#ifdef UNIV_DEBUG
267
258
/** If this is set TRUE, the program prints info whenever
269
260
UNIV_INTERN ibool               buf_debug_prints = FALSE;
270
261
#endif /* UNIV_DEBUG */
271
262
 
 
263
#ifdef UNIV_PFS_RWLOCK
 
264
/* Keys to register buffer block related rwlocks and mutexes with
 
265
performance schema */
 
266
UNIV_INTERN mysql_pfs_key_t     buf_block_lock_key;
 
267
# ifdef UNIV_SYNC_DEBUG
 
268
UNIV_INTERN mysql_pfs_key_t     buf_block_debug_latch_key;
 
269
# endif /* UNIV_SYNC_DEBUG */
 
270
#endif /* UNIV_PFS_RWLOCK */
 
271
 
 
272
#ifdef UNIV_PFS_MUTEX
 
273
UNIV_INTERN mysql_pfs_key_t     buffer_block_mutex_key;
 
274
UNIV_INTERN mysql_pfs_key_t     buf_pool_mutex_key;
 
275
UNIV_INTERN mysql_pfs_key_t     buf_pool_zip_mutex_key;
 
276
UNIV_INTERN mysql_pfs_key_t     flush_list_mutex_key;
 
277
#endif /* UNIV_PFS_MUTEX */
 
278
 
 
279
#if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK
 
280
# ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
 
281
 
 
282
/* Buffer block mutexes and rwlocks can be registered
 
283
in one group rather than individually. If PFS_GROUP_BUFFER_SYNC
 
284
is defined, register buffer block mutex and rwlock
 
285
in one group after their initialization. */
 
286
#  define PFS_GROUP_BUFFER_SYNC
 
287
 
 
288
/* This define caps the number of mutexes/rwlocks can
 
289
be registered with performance schema. Developers can
 
290
modify this define if necessary. Please note, this would
 
291
be effective only if PFS_GROUP_BUFFER_SYNC is defined. */
 
292
#  define PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER    ULINT_MAX
 
293
 
 
294
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
 
295
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
 
296
 
272
297
/** A chunk of buffers.  The buffer pool is allocated in chunks. */
273
298
struct buf_chunk_struct{
274
299
        ulint           mem_size;       /*!< allocated size of the chunk */
280
305
#endif /* !UNIV_HOTBACKUP */
281
306
 
282
307
/********************************************************************//**
 
308
Gets the smallest oldest_modification lsn for any page in the pool. Returns
 
309
zero if all modified pages have been flushed to disk.
 
310
@return oldest modification in pool, zero if none */
 
311
UNIV_INTERN
 
312
ib_uint64_t
 
313
buf_pool_get_oldest_modification(void)
 
314
/*==================================*/
 
315
{
 
316
        ulint           i;
 
317
        buf_page_t*     bpage;
 
318
        ib_uint64_t     lsn = 0;
 
319
        ib_uint64_t     oldest_lsn = 0;
 
320
 
 
321
        /* When we traverse all the flush lists we don't want another
 
322
        thread to add a dirty page to any flush list. */
 
323
        log_flush_order_mutex_enter();
 
324
 
 
325
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
326
                buf_pool_t*     buf_pool;
 
327
 
 
328
                buf_pool = buf_pool_from_array(i);
 
329
 
 
330
                buf_flush_list_mutex_enter(buf_pool);
 
331
 
 
332
                bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
 
333
 
 
334
                if (bpage != NULL) {
 
335
                        ut_ad(bpage->in_flush_list);
 
336
                        lsn = bpage->oldest_modification;
 
337
                }
 
338
 
 
339
                buf_flush_list_mutex_exit(buf_pool);
 
340
 
 
341
                if (!oldest_lsn || oldest_lsn > lsn) {
 
342
                        oldest_lsn = lsn;
 
343
                }
 
344
        }
 
345
 
 
346
        log_flush_order_mutex_exit();
 
347
 
 
348
        /* The returned answer may be out of date: the flush_list can
 
349
        change after the mutex has been released. */
 
350
 
 
351
        return(oldest_lsn);
 
352
}
 
353
 
 
354
/********************************************************************//**
 
355
Get total buffer pool statistics. */
 
356
UNIV_INTERN
 
357
void
 
358
buf_get_total_list_len(
 
359
/*===================*/
 
360
        ulint*          LRU_len,        /*!< out: length of all LRU lists */
 
361
        ulint*          free_len,       /*!< out: length of all free lists */
 
362
        ulint*          flush_list_len) /*!< out: length of all flush lists */
 
363
{
 
364
        ulint           i;
 
365
 
 
366
        *LRU_len = 0;
 
367
        *free_len = 0;
 
368
        *flush_list_len = 0;
 
369
 
 
370
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
371
                buf_pool_t*     buf_pool;
 
372
 
 
373
                buf_pool = buf_pool_from_array(i);
 
374
                *LRU_len += UT_LIST_GET_LEN(buf_pool->LRU);
 
375
                *free_len += UT_LIST_GET_LEN(buf_pool->free);
 
376
                *flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
 
377
        }
 
378
}
 
379
 
 
380
/********************************************************************//**
 
381
Get total buffer pool statistics. */
 
382
UNIV_INTERN
 
383
void
 
384
buf_get_total_stat(
 
385
/*===============*/
 
386
        buf_pool_stat_t*        tot_stat)       /*!< out: buffer pool stats */
 
387
{
 
388
        ulint                   i;
 
389
 
 
390
        memset(tot_stat, 0, sizeof(*tot_stat));
 
391
 
 
392
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
393
                buf_pool_stat_t*buf_stat;
 
394
                buf_pool_t*     buf_pool;
 
395
 
 
396
                buf_pool = buf_pool_from_array(i);
 
397
 
 
398
                buf_stat = &buf_pool->stat;
 
399
                tot_stat->n_page_gets += buf_stat->n_page_gets;
 
400
                tot_stat->n_pages_read += buf_stat->n_pages_read;
 
401
                tot_stat->n_pages_written += buf_stat->n_pages_written;
 
402
                tot_stat->n_pages_created += buf_stat->n_pages_created;
 
403
                tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read;
 
404
                tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted;
 
405
                tot_stat->n_pages_made_young += buf_stat->n_pages_made_young;
 
406
 
 
407
                tot_stat->n_pages_not_made_young +=
 
408
                        buf_stat->n_pages_not_made_young;
 
409
        }
 
410
}
 
411
 
 
412
/********************************************************************//**
 
413
Allocates a buffer block.
 
414
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
 
415
UNIV_INTERN
 
416
buf_block_t*
 
417
buf_block_alloc(
 
418
/*============*/
 
419
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
420
        ulint           zip_size)       /*!< in: compressed page size in bytes,
 
421
                                        or 0 if uncompressed tablespace */
 
422
{
 
423
        buf_block_t*    block;
 
424
        ulint           index;
 
425
        static ulint    buf_pool_index;
 
426
 
 
427
        if (buf_pool == NULL) {
 
428
                /* We are allocating memory from any buffer pool, ensure
 
429
                we spread the grace on all buffer pool instances. */
 
430
                index = buf_pool_index++ % srv_buf_pool_instances;
 
431
                buf_pool = buf_pool_from_array(index);
 
432
        }
 
433
 
 
434
        block = buf_LRU_get_free_block(buf_pool, zip_size);
 
435
 
 
436
        buf_block_set_state(block, BUF_BLOCK_MEMORY);
 
437
 
 
438
        return(block);
 
439
}
 
440
 
 
441
/********************************************************************//**
283
442
Calculates a page checksum which is stored to the page when it is written
284
443
to a file. Note that we must be careful to calculate the same value on
285
444
32-bit and 64-bit architectures.
638
797
}
639
798
 
640
799
#ifndef UNIV_HOTBACKUP
 
800
 
 
801
# ifdef PFS_GROUP_BUFFER_SYNC
 
802
/********************************************************************//**
 
803
This function registers mutexes and rwlocks in buffer blocks with
 
804
performance schema. If PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER is
 
805
defined to be a value less than chunk->size, then only mutexes
 
806
and rwlocks in the first PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER
 
807
blocks are registered. */
 
808
static
 
809
void
 
810
pfs_register_buffer_block(
 
811
/*======================*/
 
812
        buf_chunk_t*    chunk)          /*!< in/out: chunk of buffers */
 
813
{
 
814
        ulint           i;
 
815
        ulint           num_to_register;
 
816
        buf_block_t*    block;
 
817
 
 
818
        block = chunk->blocks;
 
819
 
 
820
        num_to_register = ut_min(chunk->size,
 
821
                                 PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER);
 
822
 
 
823
        for (i = 0; i < num_to_register; i++) {
 
824
                mutex_t*        mutex;
 
825
                rw_lock_t*      rwlock;
 
826
 
 
827
#  ifdef UNIV_PFS_MUTEX
 
828
                mutex = &block->mutex;
 
829
                ut_a(!mutex->pfs_psi);
 
830
                mutex->pfs_psi = (PSI_server)
 
831
                        ? PSI_server->init_mutex(buffer_block_mutex_key, mutex)
 
832
                        : NULL;
 
833
#  endif /* UNIV_PFS_MUTEX */
 
834
 
 
835
#  ifdef UNIV_PFS_RWLOCK
 
836
                rwlock = &block->lock;
 
837
                ut_a(!rwlock->pfs_psi);
 
838
                rwlock->pfs_psi = (PSI_server)
 
839
                        ? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
 
840
                        : NULL;
 
841
#  endif /* UNIV_PFS_RWLOCK */
 
842
                block++;
 
843
        }
 
844
}
 
845
# endif /* PFS_GROUP_BUFFER_SYNC */
 
846
 
641
847
/********************************************************************//**
642
848
Initializes a buffer control block when the buf_pool is created. */
643
849
static
644
850
void
645
851
buf_block_init(
646
852
/*===========*/
647
 
        buf_block_t*    block,  /*!< in: pointer to control block */
648
 
        byte*           frame)  /*!< in: pointer to buffer frame */
 
853
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
854
        buf_block_t*    block,          /*!< in: pointer to control block */
 
855
        byte*           frame)          /*!< in: pointer to buffer frame */
649
856
{
650
857
        UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
651
858
 
652
859
        block->frame = frame;
653
860
 
 
861
        block->page.buf_pool = buf_pool;
654
862
        block->page.state = BUF_BLOCK_NOT_USED;
655
863
        block->page.buf_fix_count = 0;
656
864
        block->page.io_fix = BUF_IO_NONE;
677
885
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
678
886
        page_zip_des_init(&block->page.zip);
679
887
 
680
 
        mutex_create(&block->mutex, SYNC_BUF_BLOCK);
681
 
 
682
 
        rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
 
888
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
 
889
        /* If PFS_SKIP_BUFFER_MUTEX_RWLOCK is defined, skip registration
 
890
        of buffer block mutex/rwlock with performance schema. If
 
891
        PFS_GROUP_BUFFER_SYNC is defined, skip the registration
 
892
        since buffer block mutex/rwlock will be registered later in
 
893
        pfs_register_buffer_block() */
 
894
 
 
895
        mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
 
896
        rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
 
897
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
 
898
        mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
 
899
        rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
 
900
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
 
901
 
683
902
        ut_ad(rw_lock_validate(&(block->lock)));
684
903
 
685
904
#ifdef UNIV_SYNC_DEBUG
686
 
        rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
 
905
        rw_lock_create(buf_block_debug_latch_key,
 
906
                       &block->debug_latch, SYNC_NO_ORDER_CHECK);
687
907
#endif /* UNIV_SYNC_DEBUG */
688
908
}
689
909
 
694
914
buf_chunk_t*
695
915
buf_chunk_init(
696
916
/*===========*/
 
917
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
697
918
        buf_chunk_t*    chunk,          /*!< out: chunk of buffers */
698
919
        ulint           mem_size)       /*!< in: requested size in bytes */
699
920
{
749
970
 
750
971
        for (i = chunk->size; i--; ) {
751
972
 
752
 
                buf_block_init(block, frame);
 
973
                buf_block_init(buf_pool, block, frame);
753
974
 
754
975
#ifdef HAVE_VALGRIND
755
976
                /* Wipe contents of frame to eliminate a Purify warning */
757
978
#endif
758
979
                /* Add the block to the free list */
759
980
                UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
 
981
 
760
982
                ut_d(block->page.in_free_list = TRUE);
 
983
                ut_ad(buf_pool_from_block(block) == buf_pool);
761
984
 
762
985
                block++;
763
986
                frame += UNIV_PAGE_SIZE;
764
987
        }
765
988
 
 
989
#ifdef PFS_GROUP_BUFFER_SYNC
 
990
        pfs_register_buffer_block(chunk);
 
991
#endif
766
992
        return(chunk);
767
993
}
768
994
 
781
1007
        buf_block_t*    block;
782
1008
        ulint           i;
783
1009
 
784
 
        ut_ad(buf_pool);
785
 
        ut_ad(buf_pool_mutex_own());
786
 
 
787
1010
        block = chunk->blocks;
788
1011
 
789
1012
        for (i = chunk->size; i--; block++) {
804
1027
buf_block_t*
805
1028
buf_pool_contains_zip(
806
1029
/*==================*/
807
 
        const void*     data)   /*!< in: pointer to compressed page */
 
1030
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1031
        const void*     data)           /*!< in: pointer to compressed page */
808
1032
{
809
1033
        ulint           n;
810
1034
        buf_chunk_t*    chunk = buf_pool->chunks;
811
1035
 
 
1036
        ut_ad(buf_pool);
 
1037
        ut_ad(buf_pool_mutex_own(buf_pool));
812
1038
        for (n = buf_pool->n_chunks; n--; chunk++) {
 
1039
 
813
1040
                buf_block_t* block = buf_chunk_contains_zip(chunk, data);
814
1041
 
815
1042
                if (block) {
833
1060
        buf_block_t*    block;
834
1061
        ulint           i;
835
1062
 
836
 
        ut_ad(buf_pool);
837
 
        ut_ad(buf_pool_mutex_own());
838
 
 
839
1063
        block = chunk->blocks;
840
1064
 
841
1065
        for (i = chunk->size; i--; block++) {
885
1109
        const buf_block_t*      block;
886
1110
        ulint                   i;
887
1111
 
888
 
        ut_ad(buf_pool);
889
 
        ut_ad(buf_pool_mutex_own());
890
 
 
891
1112
        block = chunk->blocks;
892
1113
 
893
1114
        for (i = chunk->size; i--; block++) {
907
1128
void
908
1129
buf_chunk_free(
909
1130
/*===========*/
 
1131
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
910
1132
        buf_chunk_t*    chunk)          /*!< out: chunk of buffers */
911
1133
{
912
1134
        buf_block_t*            block;
913
1135
        const buf_block_t*      block_end;
914
1136
 
915
 
        ut_ad(buf_pool_mutex_own());
 
1137
        ut_ad(buf_pool_mutex_own(buf_pool));
916
1138
 
917
1139
        block_end = chunk->blocks + chunk->size;
918
1140
 
940
1162
}
941
1163
 
942
1164
/********************************************************************//**
943
 
Creates the buffer pool.
944
 
@return own: buf_pool object, NULL if not enough memory or error */
945
 
UNIV_INTERN
946
 
buf_pool_t*
947
 
buf_pool_init(void)
948
 
/*===============*/
949
 
{
 
1165
Set buffer pool size variables after resizing it */
 
1166
static
 
1167
void
 
1168
buf_pool_set_sizes(void)
 
1169
/*====================*/
 
1170
{
 
1171
        ulint   i;
 
1172
        ulint   curr_size = 0;
 
1173
 
 
1174
        buf_pool_mutex_enter_all();
 
1175
 
 
1176
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1177
                buf_pool_t*     buf_pool;
 
1178
 
 
1179
                buf_pool = buf_pool_from_array(i);
 
1180
                curr_size += buf_pool->curr_pool_size;
 
1181
        }
 
1182
 
 
1183
        srv_buf_pool_curr_size = curr_size;
 
1184
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1185
 
 
1186
        buf_pool_mutex_exit_all();
 
1187
}
 
1188
 
 
1189
/********************************************************************//**
 
1190
Initialize a buffer pool instance.
 
1191
@return DB_SUCCESS if all goes well. */
 
1192
static
 
1193
ulint
 
1194
buf_pool_init_instance(
 
1195
/*===================*/
 
1196
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1197
        ulint           buf_pool_size,  /*!< in: size in bytes */
 
1198
        ulint           instance_no)    /*!< in: id of the instance */
 
1199
{
 
1200
        ulint           i;
950
1201
        buf_chunk_t*    chunk;
951
 
        ulint           i;
952
 
 
953
 
        buf_pool = mem_zalloc(sizeof(buf_pool_t));
954
1202
 
955
1203
        /* 1. Initialize general fields
956
1204
        ------------------------------- */
957
 
        mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
958
 
        mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
959
 
 
960
 
        buf_pool_mutex_enter();
961
 
 
962
 
        buf_pool->n_chunks = 1;
963
 
        buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
964
 
 
965
 
        UT_LIST_INIT(buf_pool->free);
966
 
 
967
 
        if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
968
 
                mem_free(chunk);
969
 
                mem_free(buf_pool);
970
 
                buf_pool = NULL;
971
 
                return(NULL);
 
1205
        mutex_create(buf_pool_mutex_key,
 
1206
                     &buf_pool->mutex, SYNC_BUF_POOL);
 
1207
        mutex_create(buf_pool_zip_mutex_key,
 
1208
                     &buf_pool->zip_mutex, SYNC_BUF_BLOCK);
 
1209
 
 
1210
        buf_pool_mutex_enter(buf_pool);
 
1211
 
 
1212
        if (buf_pool_size > 0) {
 
1213
                buf_pool->n_chunks = 1;
 
1214
                buf_pool->chunks = chunk = mem_zalloc(sizeof *chunk);
 
1215
 
 
1216
                UT_LIST_INIT(buf_pool->free);
 
1217
 
 
1218
                if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
 
1219
                        mem_free(chunk);
 
1220
                        mem_free(buf_pool);
 
1221
 
 
1222
                        buf_pool_mutex_exit(buf_pool);
 
1223
 
 
1224
                        return(DB_ERROR);
 
1225
                }
 
1226
 
 
1227
                buf_pool->instance_no = instance_no;
 
1228
                buf_pool->old_pool_size = buf_pool_size;
 
1229
                buf_pool->curr_size = chunk->size;
 
1230
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1231
 
 
1232
                buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
 
1233
                buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
 
1234
                
 
1235
                buf_pool->last_printout_time = ut_time();
972
1236
        }
973
 
 
974
 
        srv_buf_pool_old_size = srv_buf_pool_size;
975
 
        buf_pool->curr_size = chunk->size;
976
 
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
977
 
 
978
 
        buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
979
 
        buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
980
 
 
981
 
        buf_pool->last_printout_time = time(NULL);
982
 
 
983
1237
        /* 2. Initialize flushing fields
984
1238
        -------------------------------- */
985
1239
 
 
1240
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
 
1241
                     SYNC_BUF_FLUSH_LIST);
 
1242
 
986
1243
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
987
1244
                buf_pool->no_flush[i] = os_event_create(NULL);
988
1245
        }
989
1246
 
990
1247
        /* 3. Initialize LRU fields
991
1248
        --------------------------- */
992
 
        /* All fields are initialized by mem_zalloc(). */
993
 
 
994
 
        buf_pool_mutex_exit();
995
 
 
996
 
        btr_search_sys_create(buf_pool->curr_size
997
 
                              * UNIV_PAGE_SIZE / sizeof(void*) / 64);
998
 
 
999
 
        /* 4. Initialize the buddy allocator fields */
1000
 
        /* All fields are initialized by mem_zalloc(). */
1001
 
 
1002
 
        return(buf_pool);
 
1249
 
 
1250
        /* All fields are initialized by mem_zalloc(). */
 
1251
 
 
1252
        buf_pool_mutex_exit(buf_pool);
 
1253
 
 
1254
        return(DB_SUCCESS);
1003
1255
}
1004
1256
 
1005
1257
/********************************************************************//**
1006
 
Frees the buffer pool at shutdown.  This must not be invoked before
1007
 
freeing all mutexes. */
1008
 
UNIV_INTERN
 
1258
free one buffer pool instance */
 
1259
static
1009
1260
void
1010
 
buf_pool_free(void)
1011
 
/*===============*/
 
1261
buf_pool_free_instance(
 
1262
/*===================*/
 
1263
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
 
1264
                                        to free */
1012
1265
{
1013
1266
        buf_chunk_t*    chunk;
1014
1267
        buf_chunk_t*    chunks;
1030
1283
}
1031
1284
 
1032
1285
/********************************************************************//**
 
1286
Creates the buffer pool.
 
1287
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
 
1288
UNIV_INTERN
 
1289
ulint
 
1290
buf_pool_init(
 
1291
/*==========*/
 
1292
        ulint   total_size,     /*!< in: size of the total pool in bytes */
 
1293
        ulint   n_instances)    /*!< in: number of instances */
 
1294
{
 
1295
        ulint   i;
 
1296
 
 
1297
        /* We create an extra buffer pool instance, this instance is used
 
1298
        for flushing the flush lists, to keep track of n_flush for all
 
1299
        the buffer pools and also used as a waiting object during flushing. */
 
1300
        for (i = 0; i < n_instances; i++) {
 
1301
                buf_pool_t*     ptr;
 
1302
                ulint           size;
 
1303
 
 
1304
                ptr = mem_zalloc(sizeof(*ptr));
 
1305
 
 
1306
                size = total_size / n_instances;
 
1307
 
 
1308
                buf_pool_ptr[i] = ptr;
 
1309
 
 
1310
                if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
 
1311
 
 
1312
                        mem_free(buf_pool_ptr[i]);
 
1313
 
 
1314
                        /* Free all the instances created so far. */
 
1315
                        buf_pool_free(i);
 
1316
 
 
1317
                        return(DB_ERROR);
 
1318
                }
 
1319
        }
 
1320
 
 
1321
        buf_pool_set_sizes();
 
1322
        buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
 
1323
 
 
1324
        btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
 
1325
 
 
1326
        return(DB_SUCCESS);
 
1327
}
 
1328
 
 
1329
/********************************************************************//**
 
1330
Frees the buffer pool at shutdown.  This must not be invoked before
 
1331
freeing all mutexes. */
 
1332
UNIV_INTERN
 
1333
void
 
1334
buf_pool_free(
 
1335
/*==========*/
 
1336
        ulint   n_instances)    /*!< in: numbere of instances to free */
 
1337
{
 
1338
        ulint   i;
 
1339
 
 
1340
        for (i = 0; i < n_instances; i++) {
 
1341
                buf_pool_free_instance(buf_pool_from_array(i));
 
1342
                buf_pool_ptr[i] = NULL;
 
1343
        }
 
1344
}
 
1345
 
 
1346
/********************************************************************//**
 
1347
Drops adaptive hash index for a buffer pool instance. */
 
1348
static
 
1349
void
 
1350
buf_pool_drop_hash_index_instance(
 
1351
/*==============================*/
 
1352
        buf_pool_t*     buf_pool,               /*!< in: buffer pool instance */
 
1353
        ibool*          released_search_latch)  /*!< out: flag for signalling
 
1354
                                                whether the search latch was
 
1355
                                                released */
 
1356
{
 
1357
        buf_chunk_t*    chunks  = buf_pool->chunks;
 
1358
        buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
 
1359
 
 
1360
        while (--chunk >= chunks) {
 
1361
                ulint           i;
 
1362
                buf_block_t*    block   = chunk->blocks;
 
1363
 
 
1364
                for (i = chunk->size; i--; block++) {
 
1365
                        /* block->is_hashed cannot be modified
 
1366
                        when we have an x-latch on btr_search_latch;
 
1367
                        see the comment in buf0buf.h */
 
1368
                        
 
1369
                        if (!block->is_hashed) {
 
1370
                                continue;
 
1371
                        }
 
1372
                        
 
1373
                        /* To follow the latching order, we
 
1374
                        have to release btr_search_latch
 
1375
                        before acquiring block->latch. */
 
1376
                        rw_lock_x_unlock(&btr_search_latch);
 
1377
                        /* When we release the search latch,
 
1378
                        we must rescan all blocks, because
 
1379
                        some may become hashed again. */
 
1380
                        *released_search_latch = TRUE;
 
1381
                        
 
1382
                        rw_lock_x_lock(&block->lock);
 
1383
                        
 
1384
                        /* This should be guaranteed by the
 
1385
                        callers, which will be holding
 
1386
                        btr_search_enabled_mutex. */
 
1387
                        ut_ad(!btr_search_enabled);
 
1388
                        
 
1389
                        /* Because we did not buffer-fix the
 
1390
                        block by calling buf_block_get_gen(),
 
1391
                        it is possible that the block has been
 
1392
                        allocated for some other use after
 
1393
                        btr_search_latch was released above.
 
1394
                        We do not care which file page the
 
1395
                        block is mapped to.  All we want to do
 
1396
                        is to drop any hash entries referring
 
1397
                        to the page. */
 
1398
                        
 
1399
                        /* It is possible that
 
1400
                        block->page.state != BUF_FILE_PAGE.
 
1401
                        Even that does not matter, because
 
1402
                        btr_search_drop_page_hash_index() will
 
1403
                        check block->is_hashed before doing
 
1404
                        anything.  block->is_hashed can only
 
1405
                        be set on uncompressed file pages. */
 
1406
                        
 
1407
                        btr_search_drop_page_hash_index(block);
 
1408
                        
 
1409
                        rw_lock_x_unlock(&block->lock);
 
1410
                        
 
1411
                        rw_lock_x_lock(&btr_search_latch);
 
1412
                        
 
1413
                        ut_ad(!btr_search_enabled);
 
1414
                }
 
1415
        }
 
1416
}
 
1417
 
 
1418
/********************************************************************//**
1033
1419
Drops the adaptive hash index.  To prevent a livelock, this function
1034
1420
is only to be called while holding btr_search_latch and while
1035
1421
btr_search_enabled == FALSE. */
1046
1432
        ut_ad(!btr_search_enabled);
1047
1433
 
1048
1434
        do {
1049
 
                buf_chunk_t*    chunks  = buf_pool->chunks;
1050
 
                buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
 
1435
                ulint   i;
1051
1436
 
1052
1437
                released_search_latch = FALSE;
1053
1438
 
1054
 
                while (--chunk >= chunks) {
1055
 
                        buf_block_t*    block   = chunk->blocks;
1056
 
                        ulint           i       = chunk->size;
1057
 
 
1058
 
                        for (; i--; block++) {
1059
 
                                /* block->is_hashed cannot be modified
1060
 
                                when we have an x-latch on btr_search_latch;
1061
 
                                see the comment in buf0buf.h */
1062
 
 
1063
 
                                if (buf_block_get_state(block)
1064
 
                                    != BUF_BLOCK_FILE_PAGE
1065
 
                                    || !block->is_hashed) {
1066
 
                                        continue;
1067
 
                                }
1068
 
 
1069
 
                                /* To follow the latching order, we
1070
 
                                have to release btr_search_latch
1071
 
                                before acquiring block->latch. */
1072
 
                                rw_lock_x_unlock(&btr_search_latch);
1073
 
                                /* When we release the search latch,
1074
 
                                we must rescan all blocks, because
1075
 
                                some may become hashed again. */
1076
 
                                released_search_latch = TRUE;
1077
 
 
1078
 
                                rw_lock_x_lock(&block->lock);
1079
 
 
1080
 
                                /* This should be guaranteed by the
1081
 
                                callers, which will be holding
1082
 
                                btr_search_enabled_mutex. */
1083
 
                                ut_ad(!btr_search_enabled);
1084
 
 
1085
 
                                /* Because we did not buffer-fix the
1086
 
                                block by calling buf_block_get_gen(),
1087
 
                                it is possible that the block has been
1088
 
                                allocated for some other use after
1089
 
                                btr_search_latch was released above.
1090
 
                                We do not care which file page the
1091
 
                                block is mapped to.  All we want to do
1092
 
                                is to drop any hash entries referring
1093
 
                                to the page. */
1094
 
 
1095
 
                                /* It is possible that
1096
 
                                block->page.state != BUF_FILE_PAGE.
1097
 
                                Even that does not matter, because
1098
 
                                btr_search_drop_page_hash_index() will
1099
 
                                check block->is_hashed before doing
1100
 
                                anything.  block->is_hashed can only
1101
 
                                be set on uncompressed file pages. */
1102
 
 
1103
 
                                btr_search_drop_page_hash_index(block);
1104
 
 
1105
 
                                rw_lock_x_unlock(&block->lock);
1106
 
 
1107
 
                                rw_lock_x_lock(&btr_search_latch);
1108
 
 
1109
 
                                ut_ad(!btr_search_enabled);
1110
 
                        }
 
1439
                for (i = 0; i < srv_buf_pool_instances; i++) {
 
1440
                        buf_pool_t*     buf_pool;
 
1441
 
 
1442
                        buf_pool = buf_pool_from_array(i);
 
1443
 
 
1444
                        buf_pool_drop_hash_index_instance(
 
1445
                                buf_pool, &released_search_latch);
1111
1446
                }
 
1447
 
1112
1448
        } while (released_search_latch);
1113
1449
}
1114
1450
 
1127
1463
{
1128
1464
        buf_page_t*     b;
1129
1465
        ulint           fold;
 
1466
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1130
1467
 
1131
 
        ut_ad(buf_pool_mutex_own());
 
1468
        ut_ad(buf_pool_mutex_own(buf_pool));
1132
1469
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1133
1470
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1134
1471
        ut_a(bpage->buf_fix_count == 0);
1135
1472
        ut_ad(bpage->in_LRU_list);
1136
1473
        ut_ad(!bpage->in_zip_hash);
1137
1474
        ut_ad(bpage->in_page_hash);
1138
 
        ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
 
1475
        ut_ad(bpage == buf_page_hash_get(buf_pool,
 
1476
                                         bpage->space, bpage->offset));
 
1477
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1139
1478
#ifdef UNIV_DEBUG
1140
1479
        switch (buf_page_get_state(bpage)) {
1141
1480
        case BUF_BLOCK_ZIP_FREE:
1194
1533
}
1195
1534
 
1196
1535
/********************************************************************//**
1197
 
Shrinks the buffer pool. */
 
1536
Shrinks a buffer pool instance. */
1198
1537
static
1199
1538
void
1200
 
buf_pool_shrink(
1201
 
/*============*/
1202
 
        ulint   chunk_size)     /*!< in: number of pages to remove */
 
1539
buf_pool_shrink_instance(
 
1540
/*=====================*/
 
1541
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1542
        ulint           chunk_size)     /*!< in: number of pages to remove */
1203
1543
{
1204
1544
        buf_chunk_t*    chunks;
1205
1545
        buf_chunk_t*    chunk;
1208
1548
        buf_chunk_t*    max_chunk;
1209
1549
        buf_chunk_t*    max_free_chunk;
1210
1550
 
1211
 
        ut_ad(!buf_pool_mutex_own());
 
1551
        ut_ad(!buf_pool_mutex_own(buf_pool));
1212
1552
 
1213
1553
try_again:
1214
1554
        btr_search_disable(); /* Empty the adaptive hash index again */
1215
 
        buf_pool_mutex_enter();
 
1555
        buf_pool_mutex_enter(buf_pool);
1216
1556
 
1217
1557
shrink_again:
1218
1558
        if (buf_pool->n_chunks <= 1) {
1275
1615
 
1276
1616
                        mutex_enter(&block->mutex);
1277
1617
                        /* The following calls will temporarily
1278
 
                        release block->mutex and buf_pool_mutex.
 
1618
                        release block->mutex and buf_pool->mutex.
1279
1619
                        Therefore, we have to always retry,
1280
1620
                        even if !dirty && !nonfree. */
1281
1621
 
1291
1631
                        mutex_exit(&block->mutex);
1292
1632
                }
1293
1633
 
1294
 
                buf_pool_mutex_exit();
 
1634
                buf_pool_mutex_exit(buf_pool);
1295
1635
 
1296
1636
                /* Request for a flush of the chunk if it helps.
1297
1637
                Do not flush if there are non-free blocks, since
1300
1640
                        /* Avoid busy-waiting. */
1301
1641
                        os_thread_sleep(100000);
1302
1642
                } else if (dirty
1303
 
                           && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
1304
 
                           == ULINT_UNDEFINED) {
 
1643
                           && buf_flush_LRU(buf_pool, dirty)
 
1644
                              == ULINT_UNDEFINED) {
1305
1645
 
1306
 
                        buf_flush_wait_batch_end(BUF_FLUSH_LRU);
 
1646
                        buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
1307
1647
                }
1308
1648
 
1309
1649
                goto try_again;
1312
1652
        max_size = max_free_size;
1313
1653
        max_chunk = max_free_chunk;
1314
1654
 
1315
 
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1655
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
1316
1656
 
1317
1657
        /* Rewrite buf_pool->chunks.  Copy everything but max_chunk. */
1318
1658
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
1324
1664
               - (max_chunk + 1));
1325
1665
        ut_a(buf_pool->curr_size > max_chunk->size);
1326
1666
        buf_pool->curr_size -= max_chunk->size;
1327
 
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1667
        buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1328
1668
        chunk_size -= max_chunk->size;
1329
 
        buf_chunk_free(max_chunk);
 
1669
        buf_chunk_free(buf_pool, max_chunk);
1330
1670
        mem_free(buf_pool->chunks);
1331
1671
        buf_pool->chunks = chunks;
1332
1672
        buf_pool->n_chunks--;
1336
1676
 
1337
1677
                goto shrink_again;
1338
1678
        }
 
1679
        goto func_exit;
1339
1680
 
1340
1681
func_done:
1341
 
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1682
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
1342
1683
func_exit:
1343
 
        buf_pool_mutex_exit();
 
1684
        buf_pool_mutex_exit(buf_pool);
1344
1685
        btr_search_enable();
1345
1686
}
1346
1687
 
1347
1688
/********************************************************************//**
1348
 
Rebuild buf_pool->page_hash. */
1349
 
static
1350
 
void
1351
 
buf_pool_page_hash_rebuild(void)
1352
 
/*============================*/
 
1689
Shrinks the buffer pool. */
 
1690
static
 
1691
void
 
1692
buf_pool_shrink(
 
1693
/*============*/
 
1694
        ulint   chunk_size)     /*!< in: number of pages to remove */
 
1695
{
 
1696
        ulint   i;
 
1697
 
 
1698
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1699
                buf_pool_t*     buf_pool;
 
1700
                ulint           instance_chunk_size;
 
1701
 
 
1702
                instance_chunk_size = chunk_size / srv_buf_pool_instances;
 
1703
                buf_pool = buf_pool_from_array(i);
 
1704
                buf_pool_shrink_instance(buf_pool, instance_chunk_size);
 
1705
        }
 
1706
 
 
1707
        buf_pool_set_sizes();
 
1708
}
 
1709
 
 
1710
/********************************************************************//**
 
1711
Rebuild buf_pool->page_hash for a buffer pool instance. */
 
1712
static
 
1713
void
 
1714
buf_pool_page_hash_rebuild_instance(
 
1715
/*================================*/
 
1716
        buf_pool_t*     buf_pool)               /*!< in: buffer pool instance */
1353
1717
{
1354
1718
        ulint           i;
 
1719
        buf_page_t*     b;
 
1720
        buf_chunk_t*    chunk;
1355
1721
        ulint           n_chunks;
1356
 
        buf_chunk_t*    chunk;
 
1722
        hash_table_t*   zip_hash;
1357
1723
        hash_table_t*   page_hash;
1358
 
        hash_table_t*   zip_hash;
1359
 
        buf_page_t*     b;
1360
1724
 
1361
 
        buf_pool_mutex_enter();
 
1725
        buf_pool_mutex_enter(buf_pool);
1362
1726
 
1363
1727
        /* Free, create, and populate the hash table. */
1364
1728
        hash_table_free(buf_pool->page_hash);
1411
1775
                            buf_page_address_fold(b->space, b->offset), b);
1412
1776
        }
1413
1777
 
 
1778
        buf_flush_list_mutex_enter(buf_pool);
1414
1779
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1415
1780
             b = UT_LIST_GET_NEXT(list, b)) {
1416
1781
                ut_ad(b->in_flush_list);
1438
1803
                }
1439
1804
        }
1440
1805
 
1441
 
        buf_pool_mutex_exit();
 
1806
        buf_flush_list_mutex_exit(buf_pool);
 
1807
        buf_pool_mutex_exit(buf_pool);
 
1808
}
 
1809
 
 
1810
/********************************************************************
 
1811
Determine if a block is a sentinel for a buffer pool watch.
 
1812
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
 
1813
UNIV_INTERN
 
1814
ibool
 
1815
buf_pool_watch_is_sentinel(
 
1816
/*=======================*/
 
1817
        buf_pool_t*             buf_pool,       /*!< buffer pool instance */
 
1818
        const buf_page_t*       bpage)          /*!< in: block */
 
1819
{
 
1820
        ut_ad(buf_page_in_file(bpage));
 
1821
 
 
1822
        if (bpage < &buf_pool->watch[0]
 
1823
            || bpage >= &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
 
1824
 
 
1825
                ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE
 
1826
                      || bpage->zip.data != NULL);
 
1827
 
 
1828
                return(FALSE);
 
1829
        }
 
1830
 
 
1831
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
 
1832
        ut_ad(!bpage->in_zip_hash);
 
1833
        ut_ad(bpage->in_page_hash);
 
1834
        ut_ad(bpage->zip.data == NULL);
 
1835
        ut_ad(bpage->buf_fix_count > 0);
 
1836
        return(TRUE);
 
1837
}
 
1838
 
 
1839
/****************************************************************//**
 
1840
Add watch for the given page to be read in. Caller must have the buffer pool
 
1841
mutex reserved.
 
1842
@return NULL if watch set, block if the page is in the buffer pool */
 
1843
UNIV_INTERN
 
1844
buf_page_t*
 
1845
buf_pool_watch_set(
 
1846
/*===============*/
 
1847
        ulint   space,  /*!< in: space id */
 
1848
        ulint   offset, /*!< in: page number */
 
1849
        ulint   fold)   /*!< in: buf_page_address_fold(space, offset) */
 
1850
{
 
1851
        buf_page_t*     bpage;
 
1852
        ulint           i;
 
1853
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
1854
 
 
1855
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1856
 
 
1857
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
1858
 
 
1859
        if (UNIV_LIKELY_NULL(bpage)) {
 
1860
                if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
 
1861
                        /* The page was loaded meanwhile. */
 
1862
                        return(bpage);
 
1863
                }
 
1864
                /* Add to an existing watch. */
 
1865
                bpage->buf_fix_count++;
 
1866
                return(NULL);
 
1867
        }
 
1868
 
 
1869
        for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
 
1870
                bpage = &buf_pool->watch[i];
 
1871
 
 
1872
                ut_ad(bpage->access_time == 0);
 
1873
                ut_ad(bpage->newest_modification == 0);
 
1874
                ut_ad(bpage->oldest_modification == 0);
 
1875
                ut_ad(bpage->zip.data == NULL);
 
1876
                ut_ad(!bpage->in_zip_hash);
 
1877
 
 
1878
                switch (bpage->state) {
 
1879
                case BUF_BLOCK_POOL_WATCH:
 
1880
                        ut_ad(!bpage->in_page_hash);
 
1881
                        ut_ad(bpage->buf_fix_count == 0);
 
1882
 
 
1883
                        /* bpage is pointing to buf_pool_watch[],
 
1884
                        which is protected by buf_pool_mutex.
 
1885
                        Normally, buf_page_t objects are protected by
 
1886
                        buf_block_t::mutex or buf_pool->zip_mutex or both. */
 
1887
 
 
1888
                        bpage->state = BUF_BLOCK_ZIP_PAGE;
 
1889
                        bpage->space = space;
 
1890
                        bpage->offset = offset;
 
1891
                        bpage->buf_fix_count = 1;
 
1892
 
 
1893
                        ut_d(bpage->in_page_hash = TRUE);
 
1894
                        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
1895
                                    fold, bpage);
 
1896
                        return(NULL);
 
1897
                case BUF_BLOCK_ZIP_PAGE:
 
1898
                        ut_ad(bpage->in_page_hash);
 
1899
                        ut_ad(bpage->buf_fix_count > 0);
 
1900
                        break;
 
1901
                default:
 
1902
                        ut_error;
 
1903
                }
 
1904
        }
 
1905
 
 
1906
        /* Allocation failed.  Either the maximum number of purge
 
1907
        threads should never exceed BUF_POOL_WATCH_SIZE, or this code
 
1908
        should be modified to return a special non-NULL value and the
 
1909
        caller should purge the record directly. */
 
1910
        ut_error;
 
1911
 
 
1912
        /* Fix compiler warning */
 
1913
        return(NULL);
 
1914
}
 
1915
 
 
1916
/********************************************************************//**
 
1917
Rebuild buf_pool->page_hash. */
 
1918
static
 
1919
void
 
1920
buf_pool_page_hash_rebuild(void)
 
1921
/*============================*/
 
1922
{
 
1923
        ulint   i;
 
1924
 
 
1925
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1926
                buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
 
1927
        }
 
1928
}
 
1929
 
 
1930
/********************************************************************//**
 
1931
Increase the buffer pool size of one buffer pool instance. */
 
1932
static
 
1933
void
 
1934
buf_pool_increase_instance(
 
1935
/*=======================*/
 
1936
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instane */
 
1937
        ulint           change_size)    /*!< in: new size of the pool */
 
1938
{
 
1939
        buf_chunk_t*    chunks;
 
1940
        buf_chunk_t*    chunk;
 
1941
 
 
1942
        buf_pool_mutex_enter(buf_pool);
 
1943
        chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
 
1944
 
 
1945
        memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
 
1946
 
 
1947
        chunk = &chunks[buf_pool->n_chunks];
 
1948
 
 
1949
        if (!buf_chunk_init(buf_pool, chunk, change_size)) {
 
1950
                mem_free(chunks);
 
1951
        } else {
 
1952
                buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1953
                buf_pool->curr_size += chunk->size;
 
1954
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1955
                mem_free(buf_pool->chunks);
 
1956
                buf_pool->chunks = chunks;
 
1957
                buf_pool->n_chunks++;
 
1958
        }
 
1959
 
 
1960
        buf_pool_mutex_exit(buf_pool);
 
1961
}
 
1962
 
 
1963
/********************************************************************//**
 
1964
Increase the buffer pool size. */
 
1965
static
 
1966
void
 
1967
buf_pool_increase(
 
1968
/*==============*/
 
1969
        ulint   change_size)
 
1970
{
 
1971
        ulint   i;
 
1972
 
 
1973
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1974
                buf_pool_increase_instance(
 
1975
                        buf_pool_from_array(i),
 
1976
                        change_size / srv_buf_pool_instances);
 
1977
        }
 
1978
 
 
1979
        buf_pool_set_sizes();
1442
1980
}
1443
1981
 
1444
1982
/********************************************************************//**
1448
1986
buf_pool_resize(void)
1449
1987
/*=================*/
1450
1988
{
1451
 
        buf_pool_mutex_enter();
1452
 
 
1453
 
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
1454
 
 
1455
 
                buf_pool_mutex_exit();
 
1989
        ulint   change_size;
 
1990
        ulint   min_change_size = 1048576 * srv_buf_pool_instances;
 
1991
 
 
1992
        buf_pool_mutex_enter_all();
 
1993
  
 
1994
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
 
1995
  
 
1996
                buf_pool_mutex_exit_all();
 
1997
 
 
1998
                return;
 
1999
 
 
2000
        } else if (srv_buf_pool_curr_size + min_change_size
 
2001
                   > srv_buf_pool_size) {
 
2002
  
 
2003
                change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
 
2004
                            / UNIV_PAGE_SIZE;
 
2005
 
 
2006
                buf_pool_mutex_exit_all();
 
2007
  
 
2008
                /* Disable adaptive hash indexes and empty the index
 
2009
                in order to free up memory in the buffer pool chunks. */
 
2010
                buf_pool_shrink(change_size);
 
2011
 
 
2012
        } else if (srv_buf_pool_curr_size + min_change_size
 
2013
                   < srv_buf_pool_size) {
 
2014
 
 
2015
                /* Enlarge the buffer pool by at least one megabyte */
 
2016
  
 
2017
                change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
 
2018
 
 
2019
                buf_pool_mutex_exit_all();
 
2020
 
 
2021
                buf_pool_increase(change_size);
 
2022
        } else {
 
2023
                srv_buf_pool_size = srv_buf_pool_old_size;
 
2024
 
 
2025
                buf_pool_mutex_exit_all();
 
2026
 
1456
2027
                return;
1457
2028
        }
1458
 
 
1459
 
        if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
1460
 
 
1461
 
                buf_pool_mutex_exit();
1462
 
 
1463
 
                /* Disable adaptive hash indexes and empty the index
1464
 
                in order to free up memory in the buffer pool chunks. */
1465
 
                buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
1466
 
                                / UNIV_PAGE_SIZE);
1467
 
        } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
1468
 
 
1469
 
                /* Enlarge the buffer pool by at least one megabyte */
1470
 
 
1471
 
                ulint           mem_size
1472
 
                        = srv_buf_pool_size - srv_buf_pool_curr_size;
1473
 
                buf_chunk_t*    chunks;
1474
 
                buf_chunk_t*    chunk;
1475
 
 
1476
 
                chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1477
 
 
1478
 
                memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
1479
 
                       * sizeof *chunks);
1480
 
 
1481
 
                chunk = &chunks[buf_pool->n_chunks];
1482
 
 
1483
 
                if (!buf_chunk_init(chunk, mem_size)) {
1484
 
                        mem_free(chunks);
1485
 
                } else {
1486
 
                        buf_pool->curr_size += chunk->size;
1487
 
                        srv_buf_pool_curr_size = buf_pool->curr_size
1488
 
                                * UNIV_PAGE_SIZE;
1489
 
                        mem_free(buf_pool->chunks);
1490
 
                        buf_pool->chunks = chunks;
1491
 
                        buf_pool->n_chunks++;
 
2029
  
 
2030
        buf_pool_page_hash_rebuild();
 
2031
}
 
2032
 
 
2033
/****************************************************************//**
 
2034
Remove the sentinel block for the watch before replacing it with a real block.
 
2035
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
 
2036
the block has been replaced with the real block.
 
2037
@return reference count, to be added to the replacement block */
 
2038
static
 
2039
void
 
2040
buf_pool_watch_remove(
 
2041
/*==================*/
 
2042
        buf_pool_t*     buf_pool,       /*!< buffer pool instance */
 
2043
        ulint           fold,           /*!< in: buf_page_address_fold(
 
2044
                                        space, offset) */
 
2045
        buf_page_t*     watch)          /*!< in/out: sentinel for watch */
 
2046
{
 
2047
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2048
 
 
2049
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
 
2050
        ut_d(watch->in_page_hash = FALSE);
 
2051
        watch->buf_fix_count = 0;
 
2052
        watch->state = BUF_BLOCK_POOL_WATCH;
 
2053
}
 
2054
 
 
2055
/****************************************************************//**
 
2056
Stop watching if the page has been read in.
 
2057
buf_pool_watch_set(space,offset) must have returned NULL before. */
 
2058
UNIV_INTERN
 
2059
void
 
2060
buf_pool_watch_unset(
 
2061
/*=================*/
 
2062
        ulint   space,  /*!< in: space id */
 
2063
        ulint   offset) /*!< in: page number */
 
2064
{
 
2065
        buf_page_t*     bpage;
 
2066
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2067
        ulint           fold = buf_page_address_fold(space, offset);
 
2068
 
 
2069
        buf_pool_mutex_enter(buf_pool);
 
2070
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
2071
        /* The page must exist because buf_pool_watch_set()
 
2072
        increments buf_fix_count. */
 
2073
        ut_a(bpage);
 
2074
 
 
2075
        if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
 
2076
                mutex_t* mutex = buf_page_get_mutex(bpage);
 
2077
 
 
2078
                mutex_enter(mutex);
 
2079
                ut_a(bpage->buf_fix_count > 0);
 
2080
                bpage->buf_fix_count--;
 
2081
                mutex_exit(mutex);
 
2082
        } else {
 
2083
                ut_a(bpage->buf_fix_count > 0);
 
2084
 
 
2085
                if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
 
2086
                        buf_pool_watch_remove(buf_pool, fold, bpage);
1492
2087
                }
1493
 
 
1494
 
                srv_buf_pool_old_size = srv_buf_pool_size;
1495
 
                buf_pool_mutex_exit();
1496
2088
        }
1497
2089
 
1498
 
        buf_pool_page_hash_rebuild();
 
2090
        buf_pool_mutex_exit(buf_pool);
 
2091
}
 
2092
 
 
2093
/****************************************************************//**
 
2094
Check if the page has been read in.
 
2095
This may only be called after buf_pool_watch_set(space,offset)
 
2096
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
 
2097
@return FALSE if the given page was not read in, TRUE if it was */
 
2098
UNIV_INTERN
 
2099
ibool
 
2100
buf_pool_watch_occurred(
 
2101
/*====================*/
 
2102
        ulint   space,  /*!< in: space id */
 
2103
        ulint   offset) /*!< in: page number */
 
2104
{
 
2105
        ibool           ret;
 
2106
        buf_page_t*     bpage;
 
2107
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2108
        ulint           fold    = buf_page_address_fold(space, offset);
 
2109
 
 
2110
        buf_pool_mutex_enter(buf_pool);
 
2111
 
 
2112
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
2113
        /* The page must exist because buf_pool_watch_set()
 
2114
        increments buf_fix_count. */
 
2115
        ut_a(bpage);
 
2116
        ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
 
2117
        buf_pool_mutex_exit(buf_pool);
 
2118
 
 
2119
        return(ret);
1499
2120
}
1500
2121
 
1501
2122
/********************************************************************//**
1508
2129
/*================*/
1509
2130
        buf_page_t*     bpage)  /*!< in: buffer block of a file page */
1510
2131
{
1511
 
        buf_pool_mutex_enter();
 
2132
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
 
2133
 
 
2134
        buf_pool_mutex_enter(buf_pool);
1512
2135
 
1513
2136
        ut_a(buf_page_in_file(bpage));
1514
2137
 
1515
2138
        buf_LRU_make_block_young(bpage);
1516
2139
 
1517
 
        buf_pool_mutex_exit();
 
2140
        buf_pool_mutex_exit(buf_pool);
1518
2141
}
1519
2142
 
1520
2143
/********************************************************************//**
1532
2155
                                        read under mutex protection,
1533
2156
                                        or 0 if unknown */
1534
2157
{
1535
 
        ut_ad(!buf_pool_mutex_own());
 
2158
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
 
2159
 
 
2160
        ut_ad(!buf_pool_mutex_own(buf_pool));
1536
2161
        ut_a(buf_page_in_file(bpage));
1537
2162
 
1538
2163
        if (buf_page_peek_if_too_old(bpage)) {
1539
 
                buf_pool_mutex_enter();
 
2164
                buf_pool_mutex_enter(buf_pool);
1540
2165
                buf_LRU_make_block_young(bpage);
1541
 
                buf_pool_mutex_exit();
 
2166
                buf_pool_mutex_exit(buf_pool);
1542
2167
        } else if (!access_time) {
1543
2168
                ulint   time_ms = ut_time_ms();
1544
 
                buf_pool_mutex_enter();
 
2169
                buf_pool_mutex_enter(buf_pool);
1545
2170
                buf_page_set_accessed(bpage, time_ms);
1546
 
                buf_pool_mutex_exit();
 
2171
                buf_pool_mutex_exit(buf_pool);
1547
2172
        }
1548
2173
}
1549
2174
 
1558
2183
        ulint   offset) /*!< in: page number */
1559
2184
{
1560
2185
        buf_block_t*    block;
1561
 
 
1562
 
        buf_pool_mutex_enter();
1563
 
 
1564
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2186
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2187
 
 
2188
        buf_pool_mutex_enter(buf_pool);
 
2189
 
 
2190
        block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
1565
2191
 
1566
2192
        if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
 
2193
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
1567
2194
                block->check_index_page_at_flush = FALSE;
1568
2195
        }
1569
2196
 
1570
 
        buf_pool_mutex_exit();
 
2197
        buf_pool_mutex_exit(buf_pool);
1571
2198
}
1572
2199
 
1573
2200
/********************************************************************//**
1584
2211
{
1585
2212
        buf_block_t*    block;
1586
2213
        ibool           is_hashed;
1587
 
 
1588
 
        buf_pool_mutex_enter();
1589
 
 
1590
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2214
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2215
 
 
2216
        buf_pool_mutex_enter(buf_pool);
 
2217
 
 
2218
        block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
1591
2219
 
1592
2220
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
1593
2221
                is_hashed = FALSE;
1594
2222
        } else {
 
2223
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
1595
2224
                is_hashed = block->is_hashed;
1596
2225
        }
1597
2226
 
1598
 
        buf_pool_mutex_exit();
 
2227
        buf_pool_mutex_exit(buf_pool);
1599
2228
 
1600
2229
        return(is_hashed);
1601
2230
}
1615
2244
        ulint   offset) /*!< in: page number */
1616
2245
{
1617
2246
        buf_page_t*     bpage;
1618
 
 
1619
 
        buf_pool_mutex_enter();
1620
 
 
1621
 
        bpage = buf_page_hash_get(space, offset);
 
2247
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2248
 
 
2249
        buf_pool_mutex_enter(buf_pool);
 
2250
 
 
2251
        bpage = buf_page_hash_get(buf_pool, space, offset);
1622
2252
 
1623
2253
        if (bpage) {
 
2254
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1624
2255
                bpage->file_page_was_freed = TRUE;
1625
2256
        }
1626
2257
 
1627
 
        buf_pool_mutex_exit();
 
2258
        buf_pool_mutex_exit(buf_pool);
1628
2259
 
1629
2260
        return(bpage);
1630
2261
}
1643
2274
        ulint   offset) /*!< in: page number */
1644
2275
{
1645
2276
        buf_page_t*     bpage;
1646
 
 
1647
 
        buf_pool_mutex_enter();
1648
 
 
1649
 
        bpage = buf_page_hash_get(space, offset);
 
2277
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2278
 
 
2279
        buf_pool_mutex_enter(buf_pool);
 
2280
 
 
2281
        bpage = buf_page_hash_get(buf_pool, space, offset);
1650
2282
 
1651
2283
        if (bpage) {
 
2284
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1652
2285
                bpage->file_page_was_freed = FALSE;
1653
2286
        }
1654
2287
 
1655
 
        buf_pool_mutex_exit();
 
2288
        buf_pool_mutex_exit(buf_pool);
1656
2289
 
1657
2290
        return(bpage);
1658
2291
}
1679
2312
        mutex_t*        block_mutex;
1680
2313
        ibool           must_read;
1681
2314
        unsigned        access_time;
 
2315
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
1682
2316
 
1683
2317
#ifndef UNIV_LOG_DEBUG
1684
2318
        ut_ad(!ibuf_inside());
1686
2320
        buf_pool->stat.n_page_gets++;
1687
2321
 
1688
2322
        for (;;) {
1689
 
                buf_pool_mutex_enter();
 
2323
                buf_pool_mutex_enter(buf_pool);
1690
2324
lookup:
1691
 
                bpage = buf_page_hash_get(space, offset);
 
2325
                bpage = buf_page_hash_get(buf_pool, space, offset);
1692
2326
                if (bpage) {
 
2327
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1693
2328
                        break;
1694
2329
                }
1695
2330
 
1696
2331
                /* Page not in buf_pool: needs to be read from file */
1697
2332
 
1698
 
                buf_pool_mutex_exit();
 
2333
                buf_pool_mutex_exit(buf_pool);
1699
2334
 
1700
2335
                buf_read_page(space, zip_size, offset);
1701
2336
 
1707
2342
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
1708
2343
                /* There is no compressed page. */
1709
2344
err_exit:
1710
 
                buf_pool_mutex_exit();
 
2345
                buf_pool_mutex_exit(buf_pool);
1711
2346
                return(NULL);
1712
2347
        }
1713
2348
 
 
2349
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
 
2350
 
1714
2351
        switch (buf_page_get_state(bpage)) {
1715
2352
        case BUF_BLOCK_NOT_USED:
1716
2353
        case BUF_BLOCK_READY_FOR_USE:
1720
2357
                break;
1721
2358
        case BUF_BLOCK_ZIP_PAGE:
1722
2359
        case BUF_BLOCK_ZIP_DIRTY:
1723
 
                block_mutex = &buf_pool_zip_mutex;
 
2360
                block_mutex = &buf_pool->zip_mutex;
1724
2361
                mutex_enter(block_mutex);
1725
2362
                bpage->buf_fix_count++;
1726
2363
                goto got_block;
1748
2385
        must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
1749
2386
        access_time = buf_page_is_accessed(bpage);
1750
2387
 
1751
 
        buf_pool_mutex_exit();
 
2388
        buf_pool_mutex_exit(buf_pool);
1752
2389
 
1753
2390
        mutex_exit(block_mutex);
1754
2391
 
1820
2457
        buf_block_t*    block,  /*!< in/out: block */
1821
2458
        ibool           check)  /*!< in: TRUE=verify the page checksum */
1822
2459
{
1823
 
        const byte*     frame           = block->page.zip.data;
1824
 
        ulint           stamp_checksum  = mach_read_from_4(
1825
 
                frame + FIL_PAGE_SPACE_OR_CHKSUM);
 
2460
        const byte* frame = block->page.zip.data;
1826
2461
 
1827
2462
        ut_ad(buf_block_get_zip_size(block));
1828
2463
        ut_a(buf_block_get_space(block) != 0);
1829
2464
 
1830
 
        if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
 
2465
        if (UNIV_LIKELY(check)) {
 
2466
                ulint   stamp_checksum  = mach_read_from_4(
 
2467
                        frame + FIL_PAGE_SPACE_OR_CHKSUM);
1831
2468
                ulint   calc_checksum   = page_zip_calc_checksum(
1832
2469
                        frame, page_zip_get_size(&block->page.zip));
1833
2470
 
1878
2515
 
1879
2516
#ifndef UNIV_HOTBACKUP
1880
2517
/*******************************************************************//**
1881
 
Gets the block to whose frame the pointer is pointing to.
1882
 
@return pointer to block, never NULL */
1883
 
UNIV_INTERN
 
2518
Gets the block to whose frame the pointer is pointing to if found
 
2519
in this buffer pool instance.
 
2520
@return pointer to block */
 
2521
static
1884
2522
buf_block_t*
1885
 
buf_block_align(
1886
 
/*============*/
1887
 
        const byte*     ptr)    /*!< in: pointer to a frame */
 
2523
buf_block_align_instance(
 
2524
/*=====================*/
 
2525
        buf_pool_t*     buf_pool,       /*!< in: buffer in which the block
 
2526
                                        resides */
 
2527
        const byte*     ptr)            /*!< in: pointer to a frame */
1888
2528
{
1889
2529
        buf_chunk_t*    chunk;
1890
2530
        ulint           i;
1910
2550
                        ut_ad(block->frame == page_align(ptr));
1911
2551
#ifdef UNIV_DEBUG
1912
2552
                        /* A thread that updates these fields must
1913
 
                        hold buf_pool_mutex and block->mutex.  Acquire
 
2553
                        hold buf_pool->mutex and block->mutex.  Acquire
1914
2554
                        only the latter. */
1915
2555
                        mutex_enter(&block->mutex);
1916
2556
 
1959
2599
                }
1960
2600
        }
1961
2601
 
 
2602
        return(NULL);
 
2603
}
 
2604
 
 
2605
/*******************************************************************//**
 
2606
Gets the block to whose frame the pointer is pointing to.
 
2607
@return pointer to block, never NULL */
 
2608
UNIV_INTERN
 
2609
buf_block_t*
 
2610
buf_block_align(
 
2611
/*============*/
 
2612
        const byte*     ptr)    /*!< in: pointer to a frame */
 
2613
{
 
2614
        ulint           i;
 
2615
 
 
2616
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
2617
                buf_block_t*    block;
 
2618
 
 
2619
                block = buf_block_align_instance(
 
2620
                        buf_pool_from_array(i), ptr);
 
2621
                if (block) {
 
2622
                        return(block);
 
2623
                }
 
2624
        }
 
2625
 
1962
2626
        /* The block should always be found. */
1963
2627
        ut_error;
1964
2628
        return(NULL);
1966
2630
 
1967
2631
/********************************************************************//**
1968
2632
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
1969
 
the buf_block_t itself or a member of it
 
2633
the buf_block_t itself or a member of it. This functions checks one of
 
2634
the buffer pool instances.
1970
2635
@return TRUE if ptr belongs to a buf_block_t struct */
1971
 
UNIV_INTERN
 
2636
static
1972
2637
ibool
1973
 
buf_pointer_is_block_field(
1974
 
/*=======================*/
1975
 
        const void*             ptr)    /*!< in: pointer not
1976
 
                                        dereferenced */
 
2638
buf_pointer_is_block_field_instance(
 
2639
/*================================*/
 
2640
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
2641
        const void*     ptr)            /*!< in: pointer not dereferenced */
1977
2642
{
1978
2643
        const buf_chunk_t*              chunk   = buf_pool->chunks;
1979
2644
        const buf_chunk_t* const        echunk  = chunk + buf_pool->n_chunks;
1994
2659
}
1995
2660
 
1996
2661
/********************************************************************//**
 
2662
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
 
2663
the buf_block_t itself or a member of it
 
2664
@return TRUE if ptr belongs to a buf_block_t struct */
 
2665
UNIV_INTERN
 
2666
ibool
 
2667
buf_pointer_is_block_field(
 
2668
/*=======================*/
 
2669
        const void*     ptr)    /*!< in: pointer not dereferenced */
 
2670
{
 
2671
        ulint   i;
 
2672
 
 
2673
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
2674
                ibool   found;
 
2675
 
 
2676
                found = buf_pointer_is_block_field_instance(
 
2677
                        buf_pool_from_array(i), ptr);
 
2678
                if (found) {
 
2679
                        return(TRUE);
 
2680
                }
 
2681
        }
 
2682
 
 
2683
        return(FALSE);
 
2684
}
 
2685
 
 
2686
/********************************************************************//**
1997
2687
Find out if a buffer block was created by buf_chunk_init().
1998
2688
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
1999
2689
static
2000
2690
ibool
2001
2691
buf_block_is_uncompressed(
2002
2692
/*======================*/
2003
 
        const buf_block_t*      block)  /*!< in: pointer to block,
2004
 
                                        not dereferenced */
 
2693
        buf_pool_t*             buf_pool,       /*!< in: buffer pool instance */
 
2694
        const buf_block_t*      block)          /*!< in: pointer to block,
 
2695
                                                not dereferenced */
2005
2696
{
2006
 
        ut_ad(buf_pool_mutex_own());
 
2697
        ut_ad(buf_pool_mutex_own(buf_pool));
2007
2698
 
2008
2699
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2009
2700
                /* The pointer should be aligned. */
2010
2701
                return(FALSE);
2011
2702
        }
2012
2703
 
2013
 
        return(buf_pointer_is_block_field((void *)block));
 
2704
        return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
2014
2705
}
2015
2706
 
2016
2707
/********************************************************************//**
2027
2718
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2028
2719
        buf_block_t*    guess,  /*!< in: guessed block or NULL */
2029
2720
        ulint           mode,   /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2030
 
                                BUF_GET_NO_LATCH */
 
2721
                                BUF_GET_NO_LATCH, or
 
2722
                                BUF_GET_IF_IN_POOL_OR_WATCH */
2031
2723
        const char*     file,   /*!< in: file name */
2032
2724
        ulint           line,   /*!< in: line where called */
2033
2725
        mtr_t*          mtr)    /*!< in: mini-transaction */
2034
2726
{
2035
2727
        buf_block_t*    block;
 
2728
        ulint           fold;
2036
2729
        unsigned        access_time;
2037
2730
        ulint           fix_type;
2038
2731
        ibool           must_read;
2039
2732
        ulint           retries = 0;
 
2733
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2040
2734
 
2041
2735
        ut_ad(mtr);
2042
2736
        ut_ad(mtr->state == MTR_ACTIVE);
2044
2738
              || (rw_latch == RW_X_LATCH)
2045
2739
              || (rw_latch == RW_NO_LATCH));
2046
2740
        ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
2047
 
        ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
2048
 
              || (mode == BUF_GET_NO_LATCH));
 
2741
        ut_ad(mode == BUF_GET
 
2742
              || mode == BUF_GET_IF_IN_POOL
 
2743
              || mode == BUF_GET_NO_LATCH
 
2744
              || mode == BUF_GET_IF_IN_POOL_OR_WATCH);
2049
2745
        ut_ad(zip_size == fil_space_get_zip_size(space));
2050
2746
        ut_ad(ut_is_2pow(zip_size));
2051
2747
#ifndef UNIV_LOG_DEBUG
2052
2748
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2053
2749
#endif
2054
2750
        buf_pool->stat.n_page_gets++;
 
2751
        fold = buf_page_address_fold(space, offset);
2055
2752
loop:
2056
2753
        block = guess;
2057
 
        buf_pool_mutex_enter();
 
2754
        buf_pool_mutex_enter(buf_pool);
2058
2755
 
2059
2756
        if (block) {
2060
2757
                /* If the guess is a compressed page descriptor that
2065
2762
                the guess may be pointing to a buffer pool chunk that
2066
2763
                has been released when resizing the buffer pool. */
2067
2764
 
2068
 
                if (!buf_block_is_uncompressed(block)
 
2765
                if (!buf_block_is_uncompressed(buf_pool, block)
2069
2766
                    || offset != block->page.offset
2070
2767
                    || space != block->page.space
2071
2768
                    || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2078
2775
        }
2079
2776
 
2080
2777
        if (block == NULL) {
2081
 
                block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2778
                block = (buf_block_t*) buf_page_hash_get_low(
 
2779
                        buf_pool, space, offset, fold);
2082
2780
        }
2083
2781
 
2084
2782
loop2:
 
2783
        if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
 
2784
                block = NULL;
 
2785
        }
 
2786
 
2085
2787
        if (block == NULL) {
2086
2788
                /* Page not in buf_pool: needs to be read from file */
2087
2789
 
2088
 
                buf_pool_mutex_exit();
2089
 
 
2090
 
                if (mode == BUF_GET_IF_IN_POOL) {
 
2790
                if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
 
2791
                        block = (buf_block_t*) buf_pool_watch_set(
 
2792
                                space, offset, fold);
 
2793
 
 
2794
                        if (UNIV_LIKELY_NULL(block)) {
 
2795
 
 
2796
                                goto got_block;
 
2797
                        }
 
2798
                }
 
2799
 
 
2800
                buf_pool_mutex_exit(buf_pool);
 
2801
 
 
2802
                if (mode == BUF_GET_IF_IN_POOL
 
2803
                    || mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2091
2804
 
2092
2805
                        return(NULL);
2093
2806
                }
2122
2835
                goto loop;
2123
2836
        }
2124
2837
 
 
2838
got_block:
2125
2839
        ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
2126
2840
 
2127
2841
        must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
2128
2842
 
2129
2843
        if (must_read && mode == BUF_GET_IF_IN_POOL) {
2130
 
                /* The page is only being read to buffer */
2131
 
                buf_pool_mutex_exit();
 
2844
 
 
2845
                /* The page is being read to buffer pool,
 
2846
                but we cannot wait around for the read to
 
2847
                complete. */
 
2848
                buf_pool_mutex_exit(buf_pool);
2132
2849
 
2133
2850
                return(NULL);
2134
2851
        }
2144
2861
        case BUF_BLOCK_ZIP_DIRTY:
2145
2862
                bpage = &block->page;
2146
2863
                /* Protect bpage->buf_fix_count. */
2147
 
                mutex_enter(&buf_pool_zip_mutex);
 
2864
                mutex_enter(&buf_pool->zip_mutex);
2148
2865
 
2149
2866
                if (bpage->buf_fix_count
2150
2867
                    || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2151
2868
                        /* This condition often occurs when the buffer
2152
2869
                        is not buffer-fixed, but I/O-fixed by
2153
2870
                        buf_page_init_for_read(). */
2154
 
                        mutex_exit(&buf_pool_zip_mutex);
 
2871
                        mutex_exit(&buf_pool->zip_mutex);
2155
2872
wait_until_unfixed:
2156
2873
                        /* The block is buffer-fixed or I/O-fixed.
2157
2874
                        Try again later. */
2158
 
                        buf_pool_mutex_exit();
 
2875
                        buf_pool_mutex_exit(buf_pool);
2159
2876
                        os_thread_sleep(WAIT_FOR_READ);
2160
 
 
 
2877
  
2161
2878
                        goto loop;
2162
2879
                }
2163
2880
 
2164
2881
                /* Allocate an uncompressed page. */
2165
 
                buf_pool_mutex_exit();
2166
 
                mutex_exit(&buf_pool_zip_mutex);
 
2882
                buf_pool_mutex_exit(buf_pool);
 
2883
                mutex_exit(&buf_pool->zip_mutex);
2167
2884
 
2168
 
                block = buf_LRU_get_free_block(0);
 
2885
                block = buf_LRU_get_free_block(buf_pool, 0);
2169
2886
                ut_a(block);
2170
2887
 
2171
 
                buf_pool_mutex_enter();
 
2888
                buf_pool_mutex_enter(buf_pool);
2172
2889
                mutex_enter(&block->mutex);
2173
2890
 
2174
2891
                {
2175
 
                        buf_page_t*     hash_bpage
2176
 
                                = buf_page_hash_get(space, offset);
 
2892
                        buf_page_t*     hash_bpage;
 
2893
 
 
2894
                        hash_bpage = buf_page_hash_get_low(
 
2895
                                buf_pool, space, offset, fold);
2177
2896
 
2178
2897
                        if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2179
2898
                                /* The buf_pool->page_hash was modified
2180
 
                                while buf_pool_mutex was released.
 
2899
                                while buf_pool->mutex was released.
2181
2900
                                Free the block that was allocated. */
2182
2901
 
2183
2902
                                buf_LRU_block_free_non_file_page(block);
2193
2912
                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
2194
2913
 
2195
2914
                        /* The block was buffer-fixed or I/O-fixed
2196
 
                        while buf_pool_mutex was not held by this thread.
 
2915
                        while buf_pool->mutex was not held by this thread.
2197
2916
                        Free the block that was allocated and try again.
2198
2917
                        This should be extremely unlikely. */
2199
2918
 
2206
2925
                /* Move the compressed page from bpage to block,
2207
2926
                and uncompress it. */
2208
2927
 
2209
 
                mutex_enter(&buf_pool_zip_mutex);
 
2928
                mutex_enter(&buf_pool->zip_mutex);
2210
2929
 
2211
2930
                buf_relocate(bpage, &block->page);
2212
2931
                buf_block_init_low(block);
2236
2955
 
2237
2956
                block->page.buf_fix_count = 1;
2238
2957
                buf_block_set_io_fix(block, BUF_IO_READ);
2239
 
                rw_lock_x_lock_func(&block->lock, 0, file, line);
 
2958
                rw_lock_x_lock(&block->lock);
2240
2959
 
2241
2960
                UNIV_MEM_INVALID(bpage, sizeof *bpage);
2242
2961
 
2243
2962
                mutex_exit(&block->mutex);
2244
 
                mutex_exit(&buf_pool_zip_mutex);
 
2963
                mutex_exit(&buf_pool->zip_mutex);
2245
2964
                buf_pool->n_pend_unzip++;
2246
2965
 
2247
 
                buf_buddy_free(bpage, sizeof *bpage);
 
2966
                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
2248
2967
 
2249
 
                buf_pool_mutex_exit();
 
2968
                buf_pool_mutex_exit(buf_pool);
2250
2969
 
2251
2970
                /* Decompress the page and apply buffered operations
2252
 
                while not holding buf_pool_mutex or block->mutex. */
 
2971
                while not holding buf_pool->mutex or block->mutex. */
2253
2972
                success = buf_zip_decompress(block, srv_use_checksums);
2254
 
                ut_a(success);
2255
2973
 
2256
 
                if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
 
2974
                if (UNIV_LIKELY(success && !recv_no_ibuf_operations)) {
2257
2975
                        ibuf_merge_or_delete_for_page(block, space, offset,
2258
2976
                                                      zip_size, TRUE);
2259
2977
                }
2260
2978
 
2261
2979
                /* Unfix and unlatch the block. */
2262
 
                buf_pool_mutex_enter();
 
2980
                buf_pool_mutex_enter(buf_pool);
2263
2981
                mutex_enter(&block->mutex);
2264
2982
                block->page.buf_fix_count--;
2265
2983
                buf_block_set_io_fix(block, BUF_IO_NONE);
2266
2984
                mutex_exit(&block->mutex);
2267
2985
                buf_pool->n_pend_unzip--;
2268
2986
                rw_lock_x_unlock(&block->lock);
 
2987
 
 
2988
                if (UNIV_UNLIKELY(!success)) {
 
2989
 
 
2990
                        buf_pool_mutex_exit(buf_pool);
 
2991
                        return(NULL);
 
2992
                }
 
2993
 
2269
2994
                break;
2270
2995
 
2271
2996
        case BUF_BLOCK_ZIP_FREE:
2280
3005
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2281
3006
 
2282
3007
        mutex_enter(&block->mutex);
2283
 
#if UNIV_WORD_SIZE == 4
2284
 
        /* On 32-bit systems, there is no padding in buf_page_t.  On
2285
 
        other systems, Valgrind could complain about uninitialized pad
2286
 
        bytes. */
2287
3008
        UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
2288
 
#endif
2289
3009
 
2290
3010
        buf_block_buf_fix_inc(block, file, line);
2291
3011
 
2295
3015
 
2296
3016
        access_time = buf_page_is_accessed(&block->page);
2297
3017
 
2298
 
        buf_pool_mutex_exit();
 
3018
        buf_pool_mutex_exit(buf_pool);
2299
3019
 
2300
3020
        buf_page_set_accessed_make_young(&block->page, access_time);
2301
3021
 
2380
3100
        ulint           line,   /*!< in: line where called */
2381
3101
        mtr_t*          mtr)    /*!< in: mini-transaction */
2382
3102
{
 
3103
        buf_pool_t*     buf_pool;
2383
3104
        unsigned        access_time;
2384
3105
        ibool           success;
2385
3106
        ulint           fix_type;
2473
3194
        ut_a(ibuf_count_get(buf_block_get_space(block),
2474
3195
                            buf_block_get_page_no(block)) == 0);
2475
3196
#endif
 
3197
        buf_pool = buf_pool_from_block(block);
2476
3198
        buf_pool->stat.n_page_gets++;
2477
3199
 
2478
3200
        return(TRUE);
2494
3216
        ulint           line,   /*!< in: line where called */
2495
3217
        mtr_t*          mtr)    /*!< in: mini-transaction */
2496
3218
{
 
3219
        buf_pool_t*     buf_pool;
2497
3220
        ibool           success;
2498
3221
        ulint           fix_type;
2499
3222
 
2522
3245
 
2523
3246
        mutex_exit(&block->mutex);
2524
3247
 
 
3248
        buf_pool = buf_pool_from_block(block);
 
3249
 
2525
3250
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
2526
 
                buf_pool_mutex_enter();
 
3251
                buf_pool_mutex_enter(buf_pool);
2527
3252
                buf_LRU_make_block_young(&block->page);
2528
 
                buf_pool_mutex_exit();
 
3253
                buf_pool_mutex_exit(buf_pool);
2529
3254
        } else if (!buf_page_is_accessed(&block->page)) {
2530
3255
                /* Above, we do a dirty read on purpose, to avoid
2531
3256
                mutex contention.  The field buf_page_t::access_time
2533
3258
                field must be protected by mutex, however. */
2534
3259
                ulint   time_ms = ut_time_ms();
2535
3260
 
2536
 
                buf_pool_mutex_enter();
 
3261
                buf_pool_mutex_enter(buf_pool);
2537
3262
                buf_page_set_accessed(&block->page, time_ms);
2538
 
                buf_pool_mutex_exit();
 
3263
                buf_pool_mutex_exit(buf_pool);
2539
3264
        }
2540
3265
 
2541
3266
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
2597
3322
        buf_block_t*    block;
2598
3323
        ibool           success;
2599
3324
        ulint           fix_type;
 
3325
        buf_pool_t*     buf_pool = buf_pool_get(space_id, page_no);
2600
3326
 
2601
3327
        ut_ad(mtr);
2602
3328
        ut_ad(mtr->state == MTR_ACTIVE);
2603
3329
 
2604
 
        buf_pool_mutex_enter();
2605
 
        block = buf_block_hash_get(space_id, page_no);
 
3330
        buf_pool_mutex_enter(buf_pool);
 
3331
        block = buf_block_hash_get(buf_pool, space_id, page_no);
2606
3332
 
2607
 
        if (!block) {
2608
 
                buf_pool_mutex_exit();
 
3333
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
 
3334
                buf_pool_mutex_exit(buf_pool);
2609
3335
                return(NULL);
2610
3336
        }
2611
3337
 
 
3338
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
 
3339
 
2612
3340
        mutex_enter(&block->mutex);
2613
 
        buf_pool_mutex_exit();
 
3341
        buf_pool_mutex_exit(buf_pool);
2614
3342
 
2615
3343
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2616
3344
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2693
3421
        ulint           space,  /*!< in: space id */
2694
3422
        ulint           offset, /*!< in: offset of the page within space
2695
3423
                                in units of a page */
 
3424
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
2696
3425
        buf_block_t*    block)  /*!< in: block to init */
2697
3426
{
2698
3427
        buf_page_t*     hash_page;
 
3428
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2699
3429
 
2700
 
        ut_ad(buf_pool_mutex_own());
 
3430
        ut_ad(buf_pool_mutex_own(buf_pool));
2701
3431
        ut_ad(mutex_own(&(block->mutex)));
2702
3432
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
2703
3433
 
2715
3445
 
2716
3446
        buf_block_init_low(block);
2717
3447
 
2718
 
        block->lock_hash_val    = lock_rec_hash(space, offset);
 
3448
        block->lock_hash_val = lock_rec_hash(space, offset);
 
3449
 
 
3450
        buf_page_init_low(&block->page);
2719
3451
 
2720
3452
        /* Insert into the hash table of file pages */
2721
3453
 
2722
 
        hash_page = buf_page_hash_get(space, offset);
2723
 
 
2724
 
        if (UNIV_LIKELY_NULL(hash_page)) {
 
3454
        hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
3455
 
 
3456
        if (UNIV_LIKELY(!hash_page)) {
 
3457
        } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
 
3458
                /* Preserve the reference count. */
 
3459
                ulint   buf_fix_count = hash_page->buf_fix_count;
 
3460
 
 
3461
                ut_a(buf_fix_count > 0);
 
3462
                block->page.buf_fix_count += buf_fix_count;
 
3463
                buf_pool_watch_remove(buf_pool, fold, hash_page);
 
3464
        } else {
2725
3465
                fprintf(stderr,
2726
3466
                        "InnoDB: Error: page %lu %lu already found"
2727
3467
                        " in the hash table: %p, %p\n",
2730
3470
                        (const void*) hash_page, (const void*) block);
2731
3471
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2732
3472
                mutex_exit(&block->mutex);
2733
 
                buf_pool_mutex_exit();
 
3473
                buf_pool_mutex_exit(buf_pool);
2734
3474
                buf_print();
2735
3475
                buf_LRU_print();
2736
3476
                buf_validate();
2739
3479
                ut_error;
2740
3480
        }
2741
3481
 
2742
 
        buf_page_init_low(&block->page);
2743
 
 
2744
3482
        ut_ad(!block->page.in_zip_hash);
2745
3483
        ut_ad(!block->page.in_page_hash);
2746
3484
        ut_d(block->page.in_page_hash = TRUE);
2747
3485
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2748
 
                    buf_page_address_fold(space, offset), &block->page);
 
3486
                    fold, &block->page);
2749
3487
}
2750
3488
 
2751
3489
/********************************************************************//**
2767
3505
        ulint           space,  /*!< in: space id */
2768
3506
        ulint           zip_size,/*!< in: compressed page size, or 0 */
2769
3507
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
2770
 
        ib_int64_t      tablespace_version,/*!< in: prevents reading from a wrong
 
3508
        ib_int64_t      tablespace_version,
 
3509
                                /*!< in: prevents reading from a wrong
2771
3510
                                version of the tablespace in case we have done
2772
3511
                                DISCARD + IMPORT */
2773
3512
        ulint           offset) /*!< in: page number */
2774
3513
{
2775
3514
        buf_block_t*    block;
2776
 
        buf_page_t*     bpage;
 
3515
        buf_page_t*     bpage   = NULL;
 
3516
        buf_page_t*     watch_page;
2777
3517
        mtr_t           mtr;
 
3518
        ulint           fold;
2778
3519
        ibool           lru     = FALSE;
2779
3520
        void*           data;
 
3521
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2780
3522
 
2781
3523
        ut_ad(buf_pool);
2782
3524
 
2805
3547
            && UNIV_LIKELY(!recv_recovery_is_on())) {
2806
3548
                block = NULL;
2807
3549
        } else {
2808
 
                block = buf_LRU_get_free_block(0);
 
3550
                block = buf_LRU_get_free_block(buf_pool, 0);
2809
3551
                ut_ad(block);
 
3552
                ut_ad(buf_pool_from_block(block) == buf_pool);
2810
3553
        }
2811
3554
 
2812
 
        buf_pool_mutex_enter();
2813
 
 
2814
 
        if (buf_page_hash_get(space, offset)) {
 
3555
        fold = buf_page_address_fold(space, offset);
 
3556
 
 
3557
        buf_pool_mutex_enter(buf_pool);
 
3558
 
 
3559
        watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
3560
        if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
2815
3561
                /* The page is already in the buffer pool. */
 
3562
                watch_page = NULL;
2816
3563
err_exit:
2817
3564
                if (block) {
2818
3565
                        mutex_enter(&block->mutex);
2836
3583
        if (block) {
2837
3584
                bpage = &block->page;
2838
3585
                mutex_enter(&block->mutex);
2839
 
                buf_page_init(space, offset, block);
 
3586
 
 
3587
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
 
3588
 
 
3589
                buf_page_init(space, offset, fold, block);
2840
3590
 
2841
3591
                /* The block must be put to the LRU list, to the old blocks */
2842
3592
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2856
3606
                if (UNIV_UNLIKELY(zip_size)) {
2857
3607
                        page_zip_set_size(&block->page.zip, zip_size);
2858
3608
 
2859
 
                        /* buf_pool_mutex may be released and
 
3609
                        /* buf_pool->mutex may be released and
2860
3610
                        reacquired by buf_buddy_alloc().  Thus, we
2861
3611
                        must release block->mutex in order not to
2862
3612
                        break the latching order in the reacquisition
2863
 
                        of buf_pool_mutex.  We also must defer this
 
3613
                        of buf_pool->mutex.  We also must defer this
2864
3614
                        operation until after the block descriptor has
2865
3615
                        been added to buf_pool->LRU and
2866
3616
                        buf_pool->page_hash. */
2867
3617
                        mutex_exit(&block->mutex);
2868
 
                        data = buf_buddy_alloc(zip_size, &lru);
 
3618
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
2869
3619
                        mutex_enter(&block->mutex);
2870
3620
                        block->page.zip.data = data;
2871
3621
 
2889
3639
                control block (bpage), in order to avoid the
2890
3640
                invocation of buf_buddy_relocate_block() on
2891
3641
                uninitialized data. */
2892
 
                data = buf_buddy_alloc(zip_size, &lru);
2893
 
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
 
3642
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
3643
                bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
 
3644
 
 
3645
                /* Initialize the buf_pool pointer. */
 
3646
                bpage->buf_pool = buf_pool;
2894
3647
 
2895
3648
                /* If buf_buddy_alloc() allocated storage from the LRU list,
2896
 
                it released and reacquired buf_pool_mutex.  Thus, we must
 
3649
                it released and reacquired buf_pool->mutex.  Thus, we must
2897
3650
                check the page_hash again, as it may have been modified. */
2898
 
                if (UNIV_UNLIKELY(lru)
2899
 
                    && UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
2900
 
 
2901
 
                        /* The block was added by some other thread. */
2902
 
                        buf_buddy_free(bpage, sizeof *bpage);
2903
 
                        buf_buddy_free(data, zip_size);
2904
 
 
2905
 
                        bpage = NULL;
2906
 
                        goto func_exit;
 
3651
                if (UNIV_UNLIKELY(lru)) {
 
3652
 
 
3653
                        watch_page = buf_page_hash_get_low(
 
3654
                                buf_pool, space, offset, fold);
 
3655
 
 
3656
                        if (watch_page
 
3657
                            && !buf_pool_watch_is_sentinel(buf_pool,
 
3658
                                                           watch_page)) {
 
3659
 
 
3660
                                /* The block was added by some other thread. */
 
3661
                                watch_page = NULL;
 
3662
                                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 
3663
                                buf_buddy_free(buf_pool, data, zip_size);
 
3664
 
 
3665
                                bpage = NULL;
 
3666
                                goto func_exit;
 
3667
                        }
2907
3668
                }
2908
3669
 
2909
3670
                page_zip_des_init(&bpage->zip);
2910
3671
                page_zip_set_size(&bpage->zip, zip_size);
2911
3672
                bpage->zip.data = data;
2912
3673
 
2913
 
                mutex_enter(&buf_pool_zip_mutex);
 
3674
                mutex_enter(&buf_pool->zip_mutex);
2914
3675
                UNIV_MEM_DESC(bpage->zip.data,
2915
3676
                              page_zip_get_size(&bpage->zip), bpage);
 
3677
 
2916
3678
                buf_page_init_low(bpage);
 
3679
 
2917
3680
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
2918
3681
                bpage->space    = space;
2919
3682
                bpage->offset   = offset;
2920
3683
 
 
3684
 
2921
3685
#ifdef UNIV_DEBUG
2922
3686
                bpage->in_page_hash = FALSE;
2923
3687
                bpage->in_zip_hash = FALSE;
2927
3691
#endif /* UNIV_DEBUG */
2928
3692
 
2929
3693
                ut_d(bpage->in_page_hash = TRUE);
2930
 
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2931
 
                            buf_page_address_fold(space, offset), bpage);
 
3694
 
 
3695
                if (UNIV_LIKELY_NULL(watch_page)) {
 
3696
                        /* Preserve the reference count. */
 
3697
                        ulint   buf_fix_count = watch_page->buf_fix_count;
 
3698
                        ut_a(buf_fix_count > 0);
 
3699
                        bpage->buf_fix_count += buf_fix_count;
 
3700
                        ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
 
3701
                        buf_pool_watch_remove(buf_pool, fold, watch_page);
 
3702
                }
 
3703
 
 
3704
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
 
3705
                            bpage);
2932
3706
 
2933
3707
                /* The block must be put to the LRU list, to the old blocks */
2934
3708
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2936
3710
 
2937
3711
                buf_page_set_io_fix(bpage, BUF_IO_READ);
2938
3712
 
2939
 
                mutex_exit(&buf_pool_zip_mutex);
 
3713
                mutex_exit(&buf_pool->zip_mutex);
2940
3714
        }
2941
3715
 
2942
3716
        buf_pool->n_pend_reads++;
2943
3717
func_exit:
2944
 
        buf_pool_mutex_exit();
 
3718
        buf_pool_mutex_exit(buf_pool);
2945
3719
 
2946
3720
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
2947
3721
 
2970
3744
{
2971
3745
        buf_frame_t*    frame;
2972
3746
        buf_block_t*    block;
 
3747
        ulint           fold;
2973
3748
        buf_block_t*    free_block      = NULL;
2974
3749
        ulint           time_ms         = ut_time_ms();
 
3750
        buf_pool_t*     buf_pool        = buf_pool_get(space, offset);
2975
3751
 
2976
3752
        ut_ad(mtr);
2977
3753
        ut_ad(mtr->state == MTR_ACTIVE);
2978
3754
        ut_ad(space || !zip_size);
2979
3755
 
2980
 
        free_block = buf_LRU_get_free_block(0);
2981
 
 
2982
 
        buf_pool_mutex_enter();
2983
 
 
2984
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2985
 
 
2986
 
        if (block && buf_page_in_file(&block->page)) {
 
3756
        free_block = buf_LRU_get_free_block(buf_pool, 0);
 
3757
 
 
3758
        fold = buf_page_address_fold(space, offset);
 
3759
 
 
3760
        buf_pool_mutex_enter(buf_pool);
 
3761
 
 
3762
        block = (buf_block_t*) buf_page_hash_get_low(
 
3763
                buf_pool, space, offset, fold);
 
3764
 
 
3765
        if (block
 
3766
            && buf_page_in_file(&block->page)
 
3767
            && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2987
3768
#ifdef UNIV_IBUF_COUNT_DEBUG
2988
3769
                ut_a(ibuf_count_get(space, offset) == 0);
2989
3770
#endif
2992
3773
#endif /* UNIV_DEBUG_FILE_ACCESSES */
2993
3774
 
2994
3775
                /* Page can be found in buf_pool */
2995
 
                buf_pool_mutex_exit();
 
3776
                buf_pool_mutex_exit(buf_pool);
2996
3777
 
2997
3778
                buf_block_free(free_block);
2998
3779
 
3013
3794
 
3014
3795
        mutex_enter(&block->mutex);
3015
3796
 
3016
 
        buf_page_init(space, offset, block);
 
3797
        buf_page_init(space, offset, fold, block);
3017
3798
 
3018
3799
        /* The block must be put to the LRU list */
3019
3800
        buf_LRU_add_block(&block->page, FALSE);
3026
3807
                ibool   lru;
3027
3808
 
3028
3809
                /* Prevent race conditions during buf_buddy_alloc(),
3029
 
                which may release and reacquire buf_pool_mutex,
 
3810
                which may release and reacquire buf_pool->mutex,
3030
3811
                by IO-fixing and X-latching the block. */
3031
3812
 
3032
3813
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3034
3815
 
3035
3816
                page_zip_set_size(&block->page.zip, zip_size);
3036
3817
                mutex_exit(&block->mutex);
3037
 
                /* buf_pool_mutex may be released and reacquired by
 
3818
                /* buf_pool->mutex may be released and reacquired by
3038
3819
                buf_buddy_alloc().  Thus, we must release block->mutex
3039
3820
                in order not to break the latching order in
3040
 
                the reacquisition of buf_pool_mutex.  We also must
 
3821
                the reacquisition of buf_pool->mutex.  We also must
3041
3822
                defer this operation until after the block descriptor
3042
3823
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3043
 
                data = buf_buddy_alloc(zip_size, &lru);
 
3824
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3044
3825
                mutex_enter(&block->mutex);
3045
3826
                block->page.zip.data = data;
3046
3827
 
3058
3839
 
3059
3840
        buf_page_set_accessed(&block->page, time_ms);
3060
3841
 
3061
 
        buf_pool_mutex_exit();
 
3842
        buf_pool_mutex_exit(buf_pool);
3062
3843
 
3063
3844
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3064
3845
 
3070
3851
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3071
3852
 
3072
3853
        /* Flush pages from the end of the LRU list if necessary */
3073
 
        buf_flush_free_margin();
 
3854
        buf_flush_free_margin(buf_pool);
3074
3855
 
3075
3856
        frame = block->frame;
3076
3857
 
3106
3887
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
3107
3888
{
3108
3889
        enum buf_io_fix io_type;
 
3890
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3109
3891
        const ibool     uncompressed = (buf_page_get_state(bpage)
3110
3892
                                        == BUF_BLOCK_FILE_PAGE);
3111
3893
 
3241
4023
                }
3242
4024
        }
3243
4025
 
3244
 
        buf_pool_mutex_enter();
 
4026
        buf_pool_mutex_enter(buf_pool);
3245
4027
        mutex_enter(buf_page_get_mutex(bpage));
3246
4028
 
3247
4029
#ifdef UNIV_IBUF_COUNT_DEBUG
3305
4087
#endif /* UNIV_DEBUG */
3306
4088
 
3307
4089
        mutex_exit(buf_page_get_mutex(bpage));
3308
 
        buf_pool_mutex_exit();
3309
 
}
3310
 
 
3311
 
/*********************************************************************//**
3312
 
Invalidates the file pages in the buffer pool when an archive recovery is
3313
 
completed. All the file pages buffered must be in a replaceable state when
3314
 
this function is called: not latched and not modified. */
3315
 
UNIV_INTERN
 
4090
        buf_pool_mutex_exit(buf_pool);
 
4091
}
 
4092
 
 
4093
/*********************************************************************//**
 
4094
Asserts that all file pages in the buffer are in a replaceable state.
 
4095
@return TRUE */
 
4096
static
 
4097
ibool
 
4098
buf_all_freed_instance(
 
4099
/*===================*/
 
4100
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instancce */
 
4101
{
 
4102
        ulint           i;
 
4103
        buf_chunk_t*    chunk;
 
4104
 
 
4105
        ut_ad(buf_pool);
 
4106
 
 
4107
        buf_pool_mutex_enter(buf_pool);
 
4108
 
 
4109
        chunk = buf_pool->chunks;
 
4110
 
 
4111
        for (i = buf_pool->n_chunks; i--; chunk++) {
 
4112
 
 
4113
                const buf_block_t* block = buf_chunk_not_freed(chunk);
 
4114
 
 
4115
                if (UNIV_LIKELY_NULL(block)) {
 
4116
                        fprintf(stderr,
 
4117
                                "Page %lu %lu still fixed or dirty\n",
 
4118
                                (ulong) block->page.space,
 
4119
                                (ulong) block->page.offset);
 
4120
                        ut_error;
 
4121
                }
 
4122
        }
 
4123
 
 
4124
        buf_pool_mutex_exit(buf_pool);
 
4125
 
 
4126
        return(TRUE);
 
4127
}
 
4128
 
 
4129
/*********************************************************************//**
 
4130
Invalidates file pages in one buffer pool instance */
 
4131
static
3316
4132
void
3317
 
buf_pool_invalidate(void)
3318
 
/*=====================*/
 
4133
buf_pool_invalidate_instance(
 
4134
/*=========================*/
 
4135
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3319
4136
{
3320
4137
        ibool           freed;
3321
4138
        enum buf_flush  i;
3322
4139
 
3323
 
        buf_pool_mutex_enter();
 
4140
        buf_pool_mutex_enter(buf_pool);
3324
4141
 
3325
4142
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
3326
4143
 
3336
4153
                pool invalidation to proceed we must ensure there is NO
3337
4154
                write activity happening. */
3338
4155
                if (buf_pool->n_flush[i] > 0) {
3339
 
                        buf_pool_mutex_exit();
3340
 
                        buf_flush_wait_batch_end(i);
3341
 
                        buf_pool_mutex_enter();
 
4156
                        buf_pool_mutex_exit(buf_pool);
 
4157
                        buf_flush_wait_batch_end(buf_pool, i);
 
4158
                        buf_pool_mutex_enter(buf_pool);
3342
4159
                }
3343
4160
        }
3344
4161
 
3345
 
        buf_pool_mutex_exit();
 
4162
        buf_pool_mutex_exit(buf_pool);
3346
4163
 
3347
 
        ut_ad(buf_all_freed());
 
4164
        ut_ad(buf_all_freed_instance(buf_pool));
3348
4165
 
3349
4166
        freed = TRUE;
3350
4167
 
3351
4168
        while (freed) {
3352
 
                freed = buf_LRU_search_and_free_block(100);
 
4169
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
3353
4170
        }
3354
4171
 
3355
 
        buf_pool_mutex_enter();
 
4172
        buf_pool_mutex_enter(buf_pool);
3356
4173
 
3357
4174
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
3358
4175
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
3363
4180
        buf_pool->LRU_flush_ended = 0;
3364
4181
 
3365
4182
        memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
3366
 
        buf_refresh_io_stats();
3367
 
 
3368
 
        buf_pool_mutex_exit();
 
4183
        buf_refresh_io_stats(buf_pool);
 
4184
 
 
4185
        buf_pool_mutex_exit(buf_pool);
 
4186
}
 
4187
 
 
4188
/*********************************************************************//**
 
4189
Invalidates the file pages in the buffer pool when an archive recovery is
 
4190
completed. All the file pages buffered must be in a replaceable state when
 
4191
this function is called: not latched and not modified. */
 
4192
UNIV_INTERN
 
4193
void
 
4194
buf_pool_invalidate(void)
 
4195
/*=====================*/
 
4196
{
 
4197
        ulint   i;
 
4198
 
 
4199
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4200
                buf_pool_invalidate_instance(buf_pool_from_array(i));
 
4201
        }
3369
4202
}
3370
4203
 
3371
4204
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3372
4205
/*********************************************************************//**
3373
 
Validates the buffer buf_pool data structure.
 
4206
Validates data in one buffer pool instance
3374
4207
@return TRUE */
3375
 
UNIV_INTERN
 
4208
static
3376
4209
ibool
3377
 
buf_validate(void)
3378
 
/*==============*/
 
4210
buf_pool_validate_instance(
 
4211
/*=======================*/
 
4212
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3379
4213
{
3380
4214
        buf_page_t*     b;
3381
4215
        buf_chunk_t*    chunk;
3390
4224
 
3391
4225
        ut_ad(buf_pool);
3392
4226
 
3393
 
        buf_pool_mutex_enter();
 
4227
        buf_pool_mutex_enter(buf_pool);
3394
4228
 
3395
4229
        chunk = buf_pool->chunks;
3396
4230
 
3415
4249
                                break;
3416
4250
 
3417
4251
                        case BUF_BLOCK_FILE_PAGE:
3418
 
                                ut_a(buf_page_hash_get(buf_block_get_space(
 
4252
                                ut_a(buf_page_hash_get(buf_pool,
 
4253
                                                       buf_block_get_space(
3419
4254
                                                               block),
3420
4255
                                                       buf_block_get_page_no(
3421
4256
                                                               block))
3462
4297
                                }
3463
4298
 
3464
4299
                                n_lru++;
3465
 
 
3466
 
                                if (block->page.oldest_modification > 0) {
3467
 
                                        n_flush++;
3468
 
                                }
3469
 
 
3470
4300
                                break;
3471
4301
 
3472
4302
                        case BUF_BLOCK_NOT_USED:
3484
4314
                }
3485
4315
        }
3486
4316
 
3487
 
        mutex_enter(&buf_pool_zip_mutex);
 
4317
        mutex_enter(&buf_pool->zip_mutex);
3488
4318
 
3489
4319
        /* Check clean compressed-only blocks. */
3490
4320
 
3505
4335
                        ut_error;
3506
4336
                        break;
3507
4337
                }
 
4338
 
 
4339
                /* It is OK to read oldest_modification here because
 
4340
                we have acquired buf_pool->zip_mutex above which acts
 
4341
                as the 'block->mutex' for these bpages. */
3508
4342
                ut_a(!b->oldest_modification);
3509
 
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
 
4343
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3510
4344
 
3511
4345
                n_lru++;
3512
4346
                n_zip++;
3513
4347
        }
3514
4348
 
3515
 
        /* Check dirty compressed-only blocks. */
 
4349
        /* Check dirty blocks. */
3516
4350
 
 
4351
        buf_flush_list_mutex_enter(buf_pool);
3517
4352
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
3518
4353
             b = UT_LIST_GET_NEXT(list, b)) {
3519
4354
                ut_ad(b->in_flush_list);
 
4355
                ut_a(b->oldest_modification);
 
4356
                n_flush++;
3520
4357
 
3521
4358
                switch (buf_page_get_state(b)) {
3522
4359
                case BUF_BLOCK_ZIP_DIRTY:
3523
 
                        ut_a(b->oldest_modification);
3524
4360
                        n_lru++;
3525
 
                        n_flush++;
3526
4361
                        n_zip++;
3527
4362
                        switch (buf_page_get_io_fix(b)) {
3528
4363
                        case BUF_IO_NONE:
3529
4364
                        case BUF_IO_READ:
3530
4365
                                break;
3531
 
 
3532
4366
                        case BUF_IO_WRITE:
3533
4367
                                switch (buf_page_get_flush_type(b)) {
3534
4368
                                case BUF_FLUSH_LRU:
3558
4392
                        ut_error;
3559
4393
                        break;
3560
4394
                }
3561
 
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
 
4395
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3562
4396
        }
3563
4397
 
3564
 
        mutex_exit(&buf_pool_zip_mutex);
 
4398
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
 
4399
 
 
4400
        buf_flush_list_mutex_exit(buf_pool);
 
4401
 
 
4402
        mutex_exit(&buf_pool->zip_mutex);
3565
4403
 
3566
4404
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
3567
4405
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
3577
4415
                        (ulong) n_free);
3578
4416
                ut_error;
3579
4417
        }
3580
 
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
3581
4418
 
3582
4419
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
3583
4420
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
3584
4421
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
3585
4422
 
3586
 
        buf_pool_mutex_exit();
 
4423
        buf_pool_mutex_exit(buf_pool);
3587
4424
 
3588
4425
        ut_a(buf_LRU_validate());
3589
 
        ut_a(buf_flush_validate());
3590
 
 
3591
 
        return(TRUE);
3592
 
}
 
4426
        ut_a(buf_flush_validate(buf_pool));
 
4427
 
 
4428
        return(TRUE);
 
4429
}
 
4430
 
 
4431
/*********************************************************************//**
 
4432
Validates the buffer buf_pool data structure.
 
4433
@return TRUE */
 
4434
UNIV_INTERN
 
4435
ibool
 
4436
buf_validate(void)
 
4437
/*==============*/
 
4438
{
 
4439
        ulint   i;
 
4440
 
 
4441
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4442
                buf_pool_t*     buf_pool;
 
4443
 
 
4444
                buf_pool = buf_pool_from_array(i);
 
4445
 
 
4446
                buf_pool_validate_instance(buf_pool);
 
4447
        }
 
4448
        return(TRUE);
 
4449
}
 
4450
 
3593
4451
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3594
4452
 
3595
4453
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3596
4454
/*********************************************************************//**
3597
 
Prints info of the buffer buf_pool data structure. */
3598
 
UNIV_INTERN
 
4455
Prints info of the buffer buf_pool data structure for one instance. */
 
4456
static
3599
4457
void
3600
 
buf_print(void)
3601
 
/*===========*/
 
4458
buf_print_instance(
 
4459
/*===============*/
 
4460
        buf_pool_t*     buf_pool)
3602
4461
{
3603
4462
        dulint*         index_ids;
3604
4463
        ulint*          counts;
3617
4476
        index_ids = mem_alloc(sizeof(dulint) * size);
3618
4477
        counts = mem_alloc(sizeof(ulint) * size);
3619
4478
 
3620
 
        buf_pool_mutex_enter();
 
4479
        buf_pool_mutex_enter(buf_pool);
 
4480
        buf_flush_list_mutex_enter(buf_pool);
3621
4481
 
3622
4482
        fprintf(stderr,
3623
4483
                "buf_pool size %lu\n"
3644
4504
                (ulong) buf_pool->stat.n_pages_created,
3645
4505
                (ulong) buf_pool->stat.n_pages_written);
3646
4506
 
 
4507
        buf_flush_list_mutex_exit(buf_pool);
 
4508
 
3647
4509
        /* Count the number of blocks belonging to each index in the buffer */
3648
4510
 
3649
4511
        n_found = 0;
3684
4546
                }
3685
4547
        }
3686
4548
 
3687
 
        buf_pool_mutex_exit();
 
4549
        buf_pool_mutex_exit(buf_pool);
3688
4550
 
3689
4551
        for (i = 0; i < n_found; i++) {
3690
4552
                index = dict_index_get_if_in_cache(index_ids[i]);
3705
4567
        mem_free(index_ids);
3706
4568
        mem_free(counts);
3707
4569
 
3708
 
        ut_a(buf_validate());
 
4570
        ut_a(buf_pool_validate_instance(buf_pool));
 
4571
}
 
4572
 
 
4573
/*********************************************************************//**
 
4574
Prints info of the buffer buf_pool data structure. */
 
4575
UNIV_INTERN
 
4576
void
 
4577
buf_print(void)
 
4578
/*===========*/
 
4579
{
 
4580
        ulint   i;
 
4581
 
 
4582
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4583
                buf_pool_t*     buf_pool;
 
4584
 
 
4585
                buf_pool = buf_pool_from_array(i);
 
4586
                buf_print_instance(buf_pool);
 
4587
        }
3709
4588
}
3710
4589
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
3711
4590
 
3715
4594
@return number of latched pages */
3716
4595
UNIV_INTERN
3717
4596
ulint
3718
 
buf_get_latched_pages_number(void)
3719
 
/*==============================*/
 
4597
buf_get_latched_pages_number_instance(
 
4598
/*==================================*/
 
4599
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3720
4600
{
3721
 
        buf_chunk_t*    chunk;
3722
4601
        buf_page_t*     b;
3723
4602
        ulint           i;
 
4603
        buf_chunk_t*    chunk;
3724
4604
        ulint           fixed_pages_number = 0;
3725
4605
 
3726
 
        buf_pool_mutex_enter();
 
4606
        buf_pool_mutex_enter(buf_pool);
3727
4607
 
3728
4608
        chunk = buf_pool->chunks;
3729
4609
 
3752
4632
                }
3753
4633
        }
3754
4634
 
3755
 
        mutex_enter(&buf_pool_zip_mutex);
 
4635
        mutex_enter(&buf_pool->zip_mutex);
3756
4636
 
3757
4637
        /* Traverse the lists of clean and dirty compressed-only blocks. */
3758
4638
 
3767
4647
                }
3768
4648
        }
3769
4649
 
 
4650
        buf_flush_list_mutex_enter(buf_pool);
3770
4651
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
3771
4652
             b = UT_LIST_GET_NEXT(list, b)) {
3772
4653
                ut_ad(b->in_flush_list);
3792
4673
                }
3793
4674
        }
3794
4675
 
3795
 
        mutex_exit(&buf_pool_zip_mutex);
3796
 
        buf_pool_mutex_exit();
 
4676
        buf_flush_list_mutex_exit(buf_pool);
 
4677
        mutex_exit(&buf_pool->zip_mutex);
 
4678
        buf_pool_mutex_exit(buf_pool);
3797
4679
 
3798
4680
        return(fixed_pages_number);
3799
4681
}
 
4682
 
 
4683
/*********************************************************************//**
 
4684
Returns the number of latched pages in all the buffer pools.
 
4685
@return number of latched pages */
 
4686
UNIV_INTERN
 
4687
ulint
 
4688
buf_get_latched_pages_number(void)
 
4689
/*==============================*/
 
4690
{
 
4691
        ulint   i;
 
4692
        ulint   total_latched_pages = 0;
 
4693
 
 
4694
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4695
                buf_pool_t*     buf_pool;
 
4696
 
 
4697
                buf_pool = buf_pool_from_array(i);
 
4698
 
 
4699
                total_latched_pages += buf_get_latched_pages_number_instance(
 
4700
                        buf_pool);
 
4701
        }
 
4702
 
 
4703
        return(total_latched_pages);
 
4704
}
 
4705
 
3800
4706
#endif /* UNIV_DEBUG */
3801
4707
 
3802
4708
/*********************************************************************//**
3807
4713
buf_get_n_pending_ios(void)
3808
4714
/*=======================*/
3809
4715
{
3810
 
        return(buf_pool->n_pend_reads
3811
 
               + buf_pool->n_flush[BUF_FLUSH_LRU]
3812
 
               + buf_pool->n_flush[BUF_FLUSH_LIST]
3813
 
               + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
 
4716
        ulint   i;
 
4717
        ulint   pend_ios = 0;
 
4718
 
 
4719
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4720
                buf_pool_t*     buf_pool;
 
4721
 
 
4722
                buf_pool = buf_pool_from_array(i);
 
4723
 
 
4724
                pend_ios +=
 
4725
                        buf_pool->n_pend_reads
 
4726
                        + buf_pool->n_flush[BUF_FLUSH_LRU]
 
4727
                        + buf_pool->n_flush[BUF_FLUSH_LIST]
 
4728
                        + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
 
4729
        }
 
4730
 
 
4731
        return(pend_ios);
3814
4732
}
3815
4733
 
3816
4734
/*********************************************************************//**
3822
4740
buf_get_modified_ratio_pct(void)
3823
4741
/*============================*/
3824
4742
{
3825
 
        ulint   ratio;
3826
 
 
3827
 
        buf_pool_mutex_enter();
3828
 
 
3829
 
        ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
3830
 
                / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
3831
 
                   + UT_LIST_GET_LEN(buf_pool->free));
3832
 
 
 
4743
        ulint           ratio;
 
4744
        ulint           lru_len = 0;
 
4745
        ulint           free_len = 0;
 
4746
        ulint           flush_list_len = 0;
 
4747
 
 
4748
        buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
 
4749
 
 
4750
        ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
 
4751
  
3833
4752
        /* 1 + is there to avoid division by zero */
3834
4753
 
3835
 
        buf_pool_mutex_exit();
3836
 
 
3837
4754
        return(ratio);
3838
4755
}
3839
4756
 
3840
4757
/*********************************************************************//**
3841
4758
Prints info of the buffer i/o. */
3842
 
UNIV_INTERN
 
4759
static
3843
4760
void
3844
 
buf_print_io(
3845
 
/*=========*/
3846
 
        FILE*   file)   /*!< in/out: buffer where to print */
 
4761
buf_print_io_instance(
 
4762
/*==================*/
 
4763
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
4764
        FILE*           file)           /*!< in/out: buffer where to print */
3847
4765
{
3848
4766
        time_t  current_time;
3849
4767
        double  time_elapsed;
3851
4769
 
3852
4770
        ut_ad(buf_pool);
3853
4771
 
3854
 
        buf_pool_mutex_enter();
 
4772
        buf_pool_mutex_enter(buf_pool);
 
4773
        buf_flush_list_mutex_enter(buf_pool);
3855
4774
 
3856
4775
        fprintf(file,
3857
4776
                "Buffer pool size   %lu\n"
3873
4792
                + buf_pool->init_flush[BUF_FLUSH_LIST],
3874
4793
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
3875
4794
 
 
4795
        buf_flush_list_mutex_exit(buf_pool);
 
4796
 
3876
4797
        current_time = time(NULL);
3877
4798
        time_elapsed = 0.001 + difftime(current_time,
3878
4799
                                        buf_pool->last_printout_time);
3903
4824
                 - buf_pool->old_stat.n_pages_written)
3904
4825
                / time_elapsed);
3905
4826
 
3906
 
        n_gets_diff = buf_pool->stat.n_page_gets - buf_pool->old_stat.n_page_gets;
 
4827
        n_gets_diff = buf_pool->stat.n_page_gets
 
4828
                    - buf_pool->old_stat.n_page_gets;
3907
4829
 
3908
4830
        if (n_gets_diff) {
3909
4831
                fprintf(file,
3947
4869
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
3948
4870
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
3949
4871
 
3950
 
        buf_refresh_io_stats();
3951
 
        buf_pool_mutex_exit();
 
4872
        buf_refresh_io_stats(buf_pool);
 
4873
        buf_pool_mutex_exit(buf_pool);
 
4874
}
 
4875
 
 
4876
/*********************************************************************//**
 
4877
Prints info of the buffer i/o. */
 
4878
UNIV_INTERN
 
4879
void
 
4880
buf_print_io(
 
4881
/*=========*/
 
4882
        FILE*   file)   /*!< in/out: buffer where to print */
 
4883
{
 
4884
        ulint   i;
 
4885
 
 
4886
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4887
                buf_pool_t*     buf_pool;
 
4888
 
 
4889
                buf_pool = buf_pool_from_array(i);
 
4890
                buf_print_io_instance(buf_pool, file);
 
4891
        }
3952
4892
}
3953
4893
 
3954
4894
/**********************************************************************//**
3955
4895
Refreshes the statistics used to print per-second averages. */
3956
4896
UNIV_INTERN
3957
4897
void
3958
 
buf_refresh_io_stats(void)
3959
 
/*======================*/
 
4898
buf_refresh_io_stats(
 
4899
/*=================*/
 
4900
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3960
4901
{
3961
 
        buf_pool->last_printout_time = time(NULL);
 
4902
        buf_pool->last_printout_time = ut_time();
3962
4903
        buf_pool->old_stat = buf_pool->stat;
3963
4904
}
3964
4905
 
3965
 
/*********************************************************************//**
3966
 
Asserts that all file pages in the buffer are in a replaceable state.
3967
 
@return TRUE */
 
4906
/**********************************************************************//**
 
4907
Refreshes the statistics used to print per-second averages. */
 
4908
UNIV_INTERN
 
4909
void
 
4910
buf_refresh_io_stats_all(void)
 
4911
/*==========================*/
 
4912
{
 
4913
        ulint           i;
 
4914
 
 
4915
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4916
                buf_pool_t*     buf_pool;
 
4917
 
 
4918
                buf_pool = buf_pool_from_array(i);
 
4919
 
 
4920
                buf_refresh_io_stats(buf_pool);
 
4921
        }
 
4922
}
 
4923
 
 
4924
/**********************************************************************//**
 
4925
Check if all pages in all buffer pools are in a replacable state.
 
4926
@return FALSE if not */
3968
4927
UNIV_INTERN
3969
4928
ibool
3970
4929
buf_all_freed(void)
3971
4930
/*===============*/
3972
4931
{
3973
 
        buf_chunk_t*    chunk;
3974
 
        ulint           i;
3975
 
 
3976
 
        ut_ad(buf_pool);
3977
 
 
3978
 
        buf_pool_mutex_enter();
3979
 
 
3980
 
        chunk = buf_pool->chunks;
3981
 
 
3982
 
        for (i = buf_pool->n_chunks; i--; chunk++) {
3983
 
 
3984
 
                const buf_block_t* block = buf_chunk_not_freed(chunk);
3985
 
 
3986
 
                if (UNIV_LIKELY_NULL(block)) {
3987
 
                        fprintf(stderr,
3988
 
                                "Page %lu %lu still fixed or dirty\n",
3989
 
                                (ulong) block->page.space,
3990
 
                                (ulong) block->page.offset);
3991
 
                        ut_error;
 
4932
        ulint   i;
 
4933
 
 
4934
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4935
                buf_pool_t*     buf_pool;
 
4936
 
 
4937
                buf_pool = buf_pool_from_array(i);
 
4938
 
 
4939
                if (!buf_all_freed_instance(buf_pool)) {
 
4940
                        return(FALSE);
3992
4941
                }
3993
 
        }
3994
 
 
3995
 
        buf_pool_mutex_exit();
 
4942
        }
3996
4943
 
3997
4944
        return(TRUE);
3998
4945
}
3999
 
 
 
4946
  
4000
4947
/*********************************************************************//**
4001
4948
Checks that there currently are no pending i/o-operations for the buffer
4002
4949
pool.
4006
4953
buf_pool_check_no_pending_io(void)
4007
4954
/*==============================*/
4008
4955
{
4009
 
        ibool   ret;
4010
 
 
4011
 
        buf_pool_mutex_enter();
4012
 
 
4013
 
        if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
4014
 
            + buf_pool->n_flush[BUF_FLUSH_LIST]
4015
 
            + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
4016
 
                ret = FALSE;
4017
 
        } else {
4018
 
                ret = TRUE;
 
4956
        ulint           i;
 
4957
        ibool           ret = TRUE;
 
4958
 
 
4959
        buf_pool_mutex_enter_all();
 
4960
 
 
4961
        for (i = 0; i < srv_buf_pool_instances && ret; i++) {
 
4962
                const buf_pool_t*       buf_pool;
 
4963
 
 
4964
                buf_pool = buf_pool_from_array(i);
 
4965
 
 
4966
                if (buf_pool->n_pend_reads
 
4967
                    + buf_pool->n_flush[BUF_FLUSH_LRU]
 
4968
                    + buf_pool->n_flush[BUF_FLUSH_LIST]
 
4969
                    + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
 
4970
 
 
4971
                        ret = FALSE;
 
4972
                }
4019
4973
        }
4020
4974
 
4021
 
        buf_pool_mutex_exit();
 
4975
        buf_pool_mutex_exit_all();
4022
4976
 
4023
4977
        return(ret);
4024
4978
}
4025
4979
 
 
4980
#if 0
 
4981
Code currently not used
4026
4982
/*********************************************************************//**
4027
4983
Gets the current length of the free list of buffer blocks.
4028
4984
@return length of the free list */
4033
4989
{
4034
4990
        ulint   len;
4035
4991
 
4036
 
        buf_pool_mutex_enter();
 
4992
        buf_pool_mutex_enter(buf_pool);
4037
4993
 
4038
4994
        len = UT_LIST_GET_LEN(buf_pool->free);
4039
4995
 
4040
 
        buf_pool_mutex_exit();
 
4996
        buf_pool_mutex_exit(buf_pool);
4041
4997
 
4042
4998
        return(len);
4043
4999
}
 
5000
#endif
 
5001
 
4044
5002
#else /* !UNIV_HOTBACKUP */
4045
5003
/********************************************************************//**
4046
5004
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */