~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-11-26 22:50:54 UTC
  • mfrom: (1953.1.6 build)
  • Revision ID: mordred@inaugust.com-20101126225054-sg90svw8579t5p3i
Stewart - InnoDB 1.1.1
Monty - Fixed some autoconf tests which were returning false positives.

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;
664
872
        block->check_index_page_at_flush = FALSE;
665
873
        block->index = NULL;
666
874
 
 
875
        block->is_hashed = FALSE;
 
876
 
667
877
#ifdef UNIV_DEBUG
668
878
        block->page.in_page_hash = FALSE;
669
879
        block->page.in_zip_hash = FALSE;
677
887
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
678
888
        page_zip_des_init(&block->page.zip);
679
889
 
680
 
        mutex_create(&block->mutex, SYNC_BUF_BLOCK);
681
 
 
682
 
        rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
 
890
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
 
891
        /* If PFS_SKIP_BUFFER_MUTEX_RWLOCK is defined, skip registration
 
892
        of buffer block mutex/rwlock with performance schema. If
 
893
        PFS_GROUP_BUFFER_SYNC is defined, skip the registration
 
894
        since buffer block mutex/rwlock will be registered later in
 
895
        pfs_register_buffer_block() */
 
896
 
 
897
        mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
 
898
        rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
 
899
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
 
900
        mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
 
901
        rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
 
902
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
 
903
 
683
904
        ut_ad(rw_lock_validate(&(block->lock)));
684
905
 
685
906
#ifdef UNIV_SYNC_DEBUG
686
 
        rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
 
907
        rw_lock_create(buf_block_debug_latch_key,
 
908
                       &block->debug_latch, SYNC_NO_ORDER_CHECK);
687
909
#endif /* UNIV_SYNC_DEBUG */
688
910
}
689
911
 
694
916
buf_chunk_t*
695
917
buf_chunk_init(
696
918
/*===========*/
 
919
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
697
920
        buf_chunk_t*    chunk,          /*!< out: chunk of buffers */
698
921
        ulint           mem_size)       /*!< in: requested size in bytes */
699
922
{
749
972
 
750
973
        for (i = chunk->size; i--; ) {
751
974
 
752
 
                buf_block_init(block, frame);
 
975
                buf_block_init(buf_pool, block, frame);
753
976
 
754
977
#ifdef HAVE_VALGRIND
755
978
                /* Wipe contents of frame to eliminate a Purify warning */
757
980
#endif
758
981
                /* Add the block to the free list */
759
982
                UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
 
983
 
760
984
                ut_d(block->page.in_free_list = TRUE);
 
985
                ut_ad(buf_pool_from_block(block) == buf_pool);
761
986
 
762
987
                block++;
763
988
                frame += UNIV_PAGE_SIZE;
764
989
        }
765
990
 
 
991
#ifdef PFS_GROUP_BUFFER_SYNC
 
992
        pfs_register_buffer_block(chunk);
 
993
#endif
766
994
        return(chunk);
767
995
}
768
996
 
781
1009
        buf_block_t*    block;
782
1010
        ulint           i;
783
1011
 
784
 
        ut_ad(buf_pool);
785
 
        ut_ad(buf_pool_mutex_own());
786
 
 
787
1012
        block = chunk->blocks;
788
1013
 
789
1014
        for (i = chunk->size; i--; block++) {
804
1029
buf_block_t*
805
1030
buf_pool_contains_zip(
806
1031
/*==================*/
807
 
        const void*     data)   /*!< in: pointer to compressed page */
 
1032
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1033
        const void*     data)           /*!< in: pointer to compressed page */
808
1034
{
809
1035
        ulint           n;
810
1036
        buf_chunk_t*    chunk = buf_pool->chunks;
811
1037
 
 
1038
        ut_ad(buf_pool);
 
1039
        ut_ad(buf_pool_mutex_own(buf_pool));
812
1040
        for (n = buf_pool->n_chunks; n--; chunk++) {
 
1041
 
813
1042
                buf_block_t* block = buf_chunk_contains_zip(chunk, data);
814
1043
 
815
1044
                if (block) {
833
1062
        buf_block_t*    block;
834
1063
        ulint           i;
835
1064
 
836
 
        ut_ad(buf_pool);
837
 
        ut_ad(buf_pool_mutex_own());
838
 
 
839
1065
        block = chunk->blocks;
840
1066
 
841
1067
        for (i = chunk->size; i--; block++) {
885
1111
        const buf_block_t*      block;
886
1112
        ulint                   i;
887
1113
 
888
 
        ut_ad(buf_pool);
889
 
        ut_ad(buf_pool_mutex_own());
890
 
 
891
1114
        block = chunk->blocks;
892
1115
 
893
1116
        for (i = chunk->size; i--; block++) {
907
1130
void
908
1131
buf_chunk_free(
909
1132
/*===========*/
 
1133
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
910
1134
        buf_chunk_t*    chunk)          /*!< out: chunk of buffers */
911
1135
{
912
1136
        buf_block_t*            block;
913
1137
        const buf_block_t*      block_end;
914
1138
 
915
 
        ut_ad(buf_pool_mutex_own());
 
1139
        ut_ad(buf_pool_mutex_own(buf_pool));
916
1140
 
917
1141
        block_end = chunk->blocks + chunk->size;
918
1142
 
940
1164
}
941
1165
 
942
1166
/********************************************************************//**
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
 
{
 
1167
Set buffer pool size variables after resizing it */
 
1168
static
 
1169
void
 
1170
buf_pool_set_sizes(void)
 
1171
/*====================*/
 
1172
{
 
1173
        ulint   i;
 
1174
        ulint   curr_size = 0;
 
1175
 
 
1176
        buf_pool_mutex_enter_all();
 
1177
 
 
1178
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1179
                buf_pool_t*     buf_pool;
 
1180
 
 
1181
                buf_pool = buf_pool_from_array(i);
 
1182
                curr_size += buf_pool->curr_pool_size;
 
1183
        }
 
1184
 
 
1185
        srv_buf_pool_curr_size = curr_size;
 
1186
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1187
 
 
1188
        buf_pool_mutex_exit_all();
 
1189
}
 
1190
 
 
1191
/********************************************************************//**
 
1192
Initialize a buffer pool instance.
 
1193
@return DB_SUCCESS if all goes well. */
 
1194
static
 
1195
ulint
 
1196
buf_pool_init_instance(
 
1197
/*===================*/
 
1198
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1199
        ulint           buf_pool_size,  /*!< in: size in bytes */
 
1200
        ulint           instance_no)    /*!< in: id of the instance */
 
1201
{
 
1202
        ulint           i;
950
1203
        buf_chunk_t*    chunk;
951
 
        ulint           i;
952
 
 
953
 
        buf_pool = mem_zalloc(sizeof(buf_pool_t));
954
1204
 
955
1205
        /* 1. Initialize general fields
956
1206
        ------------------------------- */
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);
 
1207
        mutex_create(buf_pool_mutex_key,
 
1208
                     &buf_pool->mutex, SYNC_BUF_POOL);
 
1209
        mutex_create(buf_pool_zip_mutex_key,
 
1210
                     &buf_pool->zip_mutex, SYNC_BUF_BLOCK);
 
1211
 
 
1212
        buf_pool_mutex_enter(buf_pool);
 
1213
 
 
1214
        if (buf_pool_size > 0) {
 
1215
                buf_pool->n_chunks = 1;
 
1216
                buf_pool->chunks = chunk = mem_zalloc(sizeof *chunk);
 
1217
 
 
1218
                UT_LIST_INIT(buf_pool->free);
 
1219
 
 
1220
                if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
 
1221
                        mem_free(chunk);
 
1222
                        mem_free(buf_pool);
 
1223
 
 
1224
                        buf_pool_mutex_exit(buf_pool);
 
1225
 
 
1226
                        return(DB_ERROR);
 
1227
                }
 
1228
 
 
1229
                buf_pool->instance_no = instance_no;
 
1230
                buf_pool->old_pool_size = buf_pool_size;
 
1231
                buf_pool->curr_size = chunk->size;
 
1232
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1233
 
 
1234
                buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
 
1235
                buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
 
1236
                
 
1237
                buf_pool->last_printout_time = ut_time();
972
1238
        }
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
1239
        /* 2. Initialize flushing fields
984
1240
        -------------------------------- */
985
1241
 
 
1242
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
 
1243
                     SYNC_BUF_FLUSH_LIST);
 
1244
 
986
1245
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
987
1246
                buf_pool->no_flush[i] = os_event_create(NULL);
988
1247
        }
989
1248
 
990
1249
        /* 3. Initialize LRU fields
991
1250
        --------------------------- */
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);
 
1251
 
 
1252
        /* All fields are initialized by mem_zalloc(). */
 
1253
 
 
1254
        buf_pool_mutex_exit(buf_pool);
 
1255
 
 
1256
        return(DB_SUCCESS);
1003
1257
}
1004
1258
 
1005
1259
/********************************************************************//**
1006
 
Frees the buffer pool at shutdown.  This must not be invoked before
1007
 
freeing all mutexes. */
1008
 
UNIV_INTERN
 
1260
free one buffer pool instance */
 
1261
static
1009
1262
void
1010
 
buf_pool_free(void)
1011
 
/*===============*/
 
1263
buf_pool_free_instance(
 
1264
/*===================*/
 
1265
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
 
1266
                                        to free */
1012
1267
{
1013
1268
        buf_chunk_t*    chunk;
1014
1269
        buf_chunk_t*    chunks;
1030
1285
}
1031
1286
 
1032
1287
/********************************************************************//**
 
1288
Creates the buffer pool.
 
1289
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
 
1290
UNIV_INTERN
 
1291
ulint
 
1292
buf_pool_init(
 
1293
/*==========*/
 
1294
        ulint   total_size,     /*!< in: size of the total pool in bytes */
 
1295
        ulint   n_instances)    /*!< in: number of instances */
 
1296
{
 
1297
        ulint   i;
 
1298
 
 
1299
        /* We create an extra buffer pool instance, this instance is used
 
1300
        for flushing the flush lists, to keep track of n_flush for all
 
1301
        the buffer pools and also used as a waiting object during flushing. */
 
1302
        for (i = 0; i < n_instances; i++) {
 
1303
                buf_pool_t*     ptr;
 
1304
                ulint           size;
 
1305
 
 
1306
                ptr = mem_zalloc(sizeof(*ptr));
 
1307
 
 
1308
                size = total_size / n_instances;
 
1309
 
 
1310
                buf_pool_ptr[i] = ptr;
 
1311
 
 
1312
                if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
 
1313
 
 
1314
                        mem_free(buf_pool_ptr[i]);
 
1315
 
 
1316
                        /* Free all the instances created so far. */
 
1317
                        buf_pool_free(i);
 
1318
 
 
1319
                        return(DB_ERROR);
 
1320
                }
 
1321
        }
 
1322
 
 
1323
        buf_pool_set_sizes();
 
1324
        buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
 
1325
 
 
1326
        btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
 
1327
 
 
1328
        return(DB_SUCCESS);
 
1329
}
 
1330
 
 
1331
/********************************************************************//**
 
1332
Frees the buffer pool at shutdown.  This must not be invoked before
 
1333
freeing all mutexes. */
 
1334
UNIV_INTERN
 
1335
void
 
1336
buf_pool_free(
 
1337
/*==========*/
 
1338
        ulint   n_instances)    /*!< in: numbere of instances to free */
 
1339
{
 
1340
        ulint   i;
 
1341
 
 
1342
        for (i = 0; i < n_instances; i++) {
 
1343
                buf_pool_free_instance(buf_pool_from_array(i));
 
1344
                buf_pool_ptr[i] = NULL;
 
1345
        }
 
1346
}
 
1347
 
 
1348
/********************************************************************//**
 
1349
Drops adaptive hash index for a buffer pool instance. */
 
1350
static
 
1351
void
 
1352
buf_pool_drop_hash_index_instance(
 
1353
/*==============================*/
 
1354
        buf_pool_t*     buf_pool,               /*!< in: buffer pool instance */
 
1355
        ibool*          released_search_latch)  /*!< out: flag for signalling
 
1356
                                                whether the search latch was
 
1357
                                                released */
 
1358
{
 
1359
        buf_chunk_t*    chunks  = buf_pool->chunks;
 
1360
        buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
 
1361
 
 
1362
        while (--chunk >= chunks) {
 
1363
                ulint           i;
 
1364
                buf_block_t*    block   = chunk->blocks;
 
1365
 
 
1366
                for (i = chunk->size; i--; block++) {
 
1367
                        /* block->is_hashed cannot be modified
 
1368
                        when we have an x-latch on btr_search_latch;
 
1369
                        see the comment in buf0buf.h */
 
1370
                        
 
1371
                        if (!block->is_hashed) {
 
1372
                                continue;
 
1373
                        }
 
1374
                        
 
1375
                        /* To follow the latching order, we
 
1376
                        have to release btr_search_latch
 
1377
                        before acquiring block->latch. */
 
1378
                        rw_lock_x_unlock(&btr_search_latch);
 
1379
                        /* When we release the search latch,
 
1380
                        we must rescan all blocks, because
 
1381
                        some may become hashed again. */
 
1382
                        *released_search_latch = TRUE;
 
1383
                        
 
1384
                        rw_lock_x_lock(&block->lock);
 
1385
                        
 
1386
                        /* This should be guaranteed by the
 
1387
                        callers, which will be holding
 
1388
                        btr_search_enabled_mutex. */
 
1389
                        ut_ad(!btr_search_enabled);
 
1390
                        
 
1391
                        /* Because we did not buffer-fix the
 
1392
                        block by calling buf_block_get_gen(),
 
1393
                        it is possible that the block has been
 
1394
                        allocated for some other use after
 
1395
                        btr_search_latch was released above.
 
1396
                        We do not care which file page the
 
1397
                        block is mapped to.  All we want to do
 
1398
                        is to drop any hash entries referring
 
1399
                        to the page. */
 
1400
                        
 
1401
                        /* It is possible that
 
1402
                        block->page.state != BUF_FILE_PAGE.
 
1403
                        Even that does not matter, because
 
1404
                        btr_search_drop_page_hash_index() will
 
1405
                        check block->is_hashed before doing
 
1406
                        anything.  block->is_hashed can only
 
1407
                        be set on uncompressed file pages. */
 
1408
                        
 
1409
                        btr_search_drop_page_hash_index(block);
 
1410
                        
 
1411
                        rw_lock_x_unlock(&block->lock);
 
1412
                        
 
1413
                        rw_lock_x_lock(&btr_search_latch);
 
1414
                        
 
1415
                        ut_ad(!btr_search_enabled);
 
1416
                }
 
1417
        }
 
1418
}
 
1419
 
 
1420
/********************************************************************//**
1033
1421
Drops the adaptive hash index.  To prevent a livelock, this function
1034
1422
is only to be called while holding btr_search_latch and while
1035
1423
btr_search_enabled == FALSE. */
1046
1434
        ut_ad(!btr_search_enabled);
1047
1435
 
1048
1436
        do {
1049
 
                buf_chunk_t*    chunks  = buf_pool->chunks;
1050
 
                buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
 
1437
                ulint   i;
1051
1438
 
1052
1439
                released_search_latch = FALSE;
1053
1440
 
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
 
                        }
 
1441
                for (i = 0; i < srv_buf_pool_instances; i++) {
 
1442
                        buf_pool_t*     buf_pool;
 
1443
 
 
1444
                        buf_pool = buf_pool_from_array(i);
 
1445
 
 
1446
                        buf_pool_drop_hash_index_instance(
 
1447
                                buf_pool, &released_search_latch);
1111
1448
                }
 
1449
 
1112
1450
        } while (released_search_latch);
1113
1451
}
1114
1452
 
1127
1465
{
1128
1466
        buf_page_t*     b;
1129
1467
        ulint           fold;
 
1468
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1130
1469
 
1131
 
        ut_ad(buf_pool_mutex_own());
 
1470
        ut_ad(buf_pool_mutex_own(buf_pool));
1132
1471
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1133
1472
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1134
1473
        ut_a(bpage->buf_fix_count == 0);
1135
1474
        ut_ad(bpage->in_LRU_list);
1136
1475
        ut_ad(!bpage->in_zip_hash);
1137
1476
        ut_ad(bpage->in_page_hash);
1138
 
        ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
 
1477
        ut_ad(bpage == buf_page_hash_get(buf_pool,
 
1478
                                         bpage->space, bpage->offset));
 
1479
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1139
1480
#ifdef UNIV_DEBUG
1140
1481
        switch (buf_page_get_state(bpage)) {
1141
1482
        case BUF_BLOCK_ZIP_FREE:
1194
1535
}
1195
1536
 
1196
1537
/********************************************************************//**
1197
 
Shrinks the buffer pool. */
 
1538
Shrinks a buffer pool instance. */
1198
1539
static
1199
1540
void
1200
 
buf_pool_shrink(
1201
 
/*============*/
1202
 
        ulint   chunk_size)     /*!< in: number of pages to remove */
 
1541
buf_pool_shrink_instance(
 
1542
/*=====================*/
 
1543
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1544
        ulint           chunk_size)     /*!< in: number of pages to remove */
1203
1545
{
1204
1546
        buf_chunk_t*    chunks;
1205
1547
        buf_chunk_t*    chunk;
1208
1550
        buf_chunk_t*    max_chunk;
1209
1551
        buf_chunk_t*    max_free_chunk;
1210
1552
 
1211
 
        ut_ad(!buf_pool_mutex_own());
 
1553
        ut_ad(!buf_pool_mutex_own(buf_pool));
1212
1554
 
1213
1555
try_again:
1214
1556
        btr_search_disable(); /* Empty the adaptive hash index again */
1215
 
        buf_pool_mutex_enter();
 
1557
        buf_pool_mutex_enter(buf_pool);
1216
1558
 
1217
1559
shrink_again:
1218
1560
        if (buf_pool->n_chunks <= 1) {
1275
1617
 
1276
1618
                        mutex_enter(&block->mutex);
1277
1619
                        /* The following calls will temporarily
1278
 
                        release block->mutex and buf_pool_mutex.
 
1620
                        release block->mutex and buf_pool->mutex.
1279
1621
                        Therefore, we have to always retry,
1280
1622
                        even if !dirty && !nonfree. */
1281
1623
 
1291
1633
                        mutex_exit(&block->mutex);
1292
1634
                }
1293
1635
 
1294
 
                buf_pool_mutex_exit();
 
1636
                buf_pool_mutex_exit(buf_pool);
1295
1637
 
1296
1638
                /* Request for a flush of the chunk if it helps.
1297
1639
                Do not flush if there are non-free blocks, since
1300
1642
                        /* Avoid busy-waiting. */
1301
1643
                        os_thread_sleep(100000);
1302
1644
                } else if (dirty
1303
 
                           && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
1304
 
                           == ULINT_UNDEFINED) {
 
1645
                           && buf_flush_LRU(buf_pool, dirty)
 
1646
                              == ULINT_UNDEFINED) {
1305
1647
 
1306
 
                        buf_flush_wait_batch_end(BUF_FLUSH_LRU);
 
1648
                        buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
1307
1649
                }
1308
1650
 
1309
1651
                goto try_again;
1312
1654
        max_size = max_free_size;
1313
1655
        max_chunk = max_free_chunk;
1314
1656
 
1315
 
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1657
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
1316
1658
 
1317
1659
        /* Rewrite buf_pool->chunks.  Copy everything but max_chunk. */
1318
1660
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
1324
1666
               - (max_chunk + 1));
1325
1667
        ut_a(buf_pool->curr_size > max_chunk->size);
1326
1668
        buf_pool->curr_size -= max_chunk->size;
1327
 
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1669
        buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1328
1670
        chunk_size -= max_chunk->size;
1329
 
        buf_chunk_free(max_chunk);
 
1671
        buf_chunk_free(buf_pool, max_chunk);
1330
1672
        mem_free(buf_pool->chunks);
1331
1673
        buf_pool->chunks = chunks;
1332
1674
        buf_pool->n_chunks--;
1336
1678
 
1337
1679
                goto shrink_again;
1338
1680
        }
 
1681
        goto func_exit;
1339
1682
 
1340
1683
func_done:
1341
 
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1684
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
1342
1685
func_exit:
1343
 
        buf_pool_mutex_exit();
 
1686
        buf_pool_mutex_exit(buf_pool);
1344
1687
        btr_search_enable();
1345
1688
}
1346
1689
 
1347
1690
/********************************************************************//**
1348
 
Rebuild buf_pool->page_hash. */
1349
 
static
1350
 
void
1351
 
buf_pool_page_hash_rebuild(void)
1352
 
/*============================*/
 
1691
Shrinks the buffer pool. */
 
1692
static
 
1693
void
 
1694
buf_pool_shrink(
 
1695
/*============*/
 
1696
        ulint   chunk_size)     /*!< in: number of pages to remove */
 
1697
{
 
1698
        ulint   i;
 
1699
 
 
1700
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1701
                buf_pool_t*     buf_pool;
 
1702
                ulint           instance_chunk_size;
 
1703
 
 
1704
                instance_chunk_size = chunk_size / srv_buf_pool_instances;
 
1705
                buf_pool = buf_pool_from_array(i);
 
1706
                buf_pool_shrink_instance(buf_pool, instance_chunk_size);
 
1707
        }
 
1708
 
 
1709
        buf_pool_set_sizes();
 
1710
}
 
1711
 
 
1712
/********************************************************************//**
 
1713
Rebuild buf_pool->page_hash for a buffer pool instance. */
 
1714
static
 
1715
void
 
1716
buf_pool_page_hash_rebuild_instance(
 
1717
/*================================*/
 
1718
        buf_pool_t*     buf_pool)               /*!< in: buffer pool instance */
1353
1719
{
1354
1720
        ulint           i;
 
1721
        buf_page_t*     b;
 
1722
        buf_chunk_t*    chunk;
1355
1723
        ulint           n_chunks;
1356
 
        buf_chunk_t*    chunk;
 
1724
        hash_table_t*   zip_hash;
1357
1725
        hash_table_t*   page_hash;
1358
 
        hash_table_t*   zip_hash;
1359
 
        buf_page_t*     b;
1360
1726
 
1361
 
        buf_pool_mutex_enter();
 
1727
        buf_pool_mutex_enter(buf_pool);
1362
1728
 
1363
1729
        /* Free, create, and populate the hash table. */
1364
1730
        hash_table_free(buf_pool->page_hash);
1411
1777
                            buf_page_address_fold(b->space, b->offset), b);
1412
1778
        }
1413
1779
 
 
1780
        buf_flush_list_mutex_enter(buf_pool);
1414
1781
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1415
1782
             b = UT_LIST_GET_NEXT(list, b)) {
1416
1783
                ut_ad(b->in_flush_list);
1438
1805
                }
1439
1806
        }
1440
1807
 
1441
 
        buf_pool_mutex_exit();
 
1808
        buf_flush_list_mutex_exit(buf_pool);
 
1809
        buf_pool_mutex_exit(buf_pool);
 
1810
}
 
1811
 
 
1812
/********************************************************************
 
1813
Determine if a block is a sentinel for a buffer pool watch.
 
1814
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
 
1815
UNIV_INTERN
 
1816
ibool
 
1817
buf_pool_watch_is_sentinel(
 
1818
/*=======================*/
 
1819
        buf_pool_t*             buf_pool,       /*!< buffer pool instance */
 
1820
        const buf_page_t*       bpage)          /*!< in: block */
 
1821
{
 
1822
        ut_ad(buf_page_in_file(bpage));
 
1823
 
 
1824
        if (bpage < &buf_pool->watch[0]
 
1825
            || bpage >= &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
 
1826
 
 
1827
                ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE
 
1828
                      || bpage->zip.data != NULL);
 
1829
 
 
1830
                return(FALSE);
 
1831
        }
 
1832
 
 
1833
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
 
1834
        ut_ad(!bpage->in_zip_hash);
 
1835
        ut_ad(bpage->in_page_hash);
 
1836
        ut_ad(bpage->zip.data == NULL);
 
1837
        ut_ad(bpage->buf_fix_count > 0);
 
1838
        return(TRUE);
 
1839
}
 
1840
 
 
1841
/****************************************************************//**
 
1842
Add watch for the given page to be read in. Caller must have the buffer pool
 
1843
mutex reserved.
 
1844
@return NULL if watch set, block if the page is in the buffer pool */
 
1845
UNIV_INTERN
 
1846
buf_page_t*
 
1847
buf_pool_watch_set(
 
1848
/*===============*/
 
1849
        ulint   space,  /*!< in: space id */
 
1850
        ulint   offset, /*!< in: page number */
 
1851
        ulint   fold)   /*!< in: buf_page_address_fold(space, offset) */
 
1852
{
 
1853
        buf_page_t*     bpage;
 
1854
        ulint           i;
 
1855
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
1856
 
 
1857
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1858
 
 
1859
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
1860
 
 
1861
        if (UNIV_LIKELY_NULL(bpage)) {
 
1862
                if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
 
1863
                        /* The page was loaded meanwhile. */
 
1864
                        return(bpage);
 
1865
                }
 
1866
                /* Add to an existing watch. */
 
1867
                bpage->buf_fix_count++;
 
1868
                return(NULL);
 
1869
        }
 
1870
 
 
1871
        for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
 
1872
                bpage = &buf_pool->watch[i];
 
1873
 
 
1874
                ut_ad(bpage->access_time == 0);
 
1875
                ut_ad(bpage->newest_modification == 0);
 
1876
                ut_ad(bpage->oldest_modification == 0);
 
1877
                ut_ad(bpage->zip.data == NULL);
 
1878
                ut_ad(!bpage->in_zip_hash);
 
1879
 
 
1880
                switch (bpage->state) {
 
1881
                case BUF_BLOCK_POOL_WATCH:
 
1882
                        ut_ad(!bpage->in_page_hash);
 
1883
                        ut_ad(bpage->buf_fix_count == 0);
 
1884
 
 
1885
                        /* bpage is pointing to buf_pool_watch[],
 
1886
                        which is protected by buf_pool_mutex.
 
1887
                        Normally, buf_page_t objects are protected by
 
1888
                        buf_block_t::mutex or buf_pool->zip_mutex or both. */
 
1889
 
 
1890
                        bpage->state = BUF_BLOCK_ZIP_PAGE;
 
1891
                        bpage->space = space;
 
1892
                        bpage->offset = offset;
 
1893
                        bpage->buf_fix_count = 1;
 
1894
 
 
1895
                        ut_d(bpage->in_page_hash = TRUE);
 
1896
                        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
1897
                                    fold, bpage);
 
1898
                        return(NULL);
 
1899
                case BUF_BLOCK_ZIP_PAGE:
 
1900
                        ut_ad(bpage->in_page_hash);
 
1901
                        ut_ad(bpage->buf_fix_count > 0);
 
1902
                        break;
 
1903
                default:
 
1904
                        ut_error;
 
1905
                }
 
1906
        }
 
1907
 
 
1908
        /* Allocation failed.  Either the maximum number of purge
 
1909
        threads should never exceed BUF_POOL_WATCH_SIZE, or this code
 
1910
        should be modified to return a special non-NULL value and the
 
1911
        caller should purge the record directly. */
 
1912
        ut_error;
 
1913
 
 
1914
        /* Fix compiler warning */
 
1915
        return(NULL);
 
1916
}
 
1917
 
 
1918
/********************************************************************//**
 
1919
Rebuild buf_pool->page_hash. */
 
1920
static
 
1921
void
 
1922
buf_pool_page_hash_rebuild(void)
 
1923
/*============================*/
 
1924
{
 
1925
        ulint   i;
 
1926
 
 
1927
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1928
                buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
 
1929
        }
 
1930
}
 
1931
 
 
1932
/********************************************************************//**
 
1933
Increase the buffer pool size of one buffer pool instance. */
 
1934
static
 
1935
void
 
1936
buf_pool_increase_instance(
 
1937
/*=======================*/
 
1938
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instane */
 
1939
        ulint           change_size)    /*!< in: new size of the pool */
 
1940
{
 
1941
        buf_chunk_t*    chunks;
 
1942
        buf_chunk_t*    chunk;
 
1943
 
 
1944
        buf_pool_mutex_enter(buf_pool);
 
1945
        chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
 
1946
 
 
1947
        memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
 
1948
 
 
1949
        chunk = &chunks[buf_pool->n_chunks];
 
1950
 
 
1951
        if (!buf_chunk_init(buf_pool, chunk, change_size)) {
 
1952
                mem_free(chunks);
 
1953
        } else {
 
1954
                buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1955
                buf_pool->curr_size += chunk->size;
 
1956
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1957
                mem_free(buf_pool->chunks);
 
1958
                buf_pool->chunks = chunks;
 
1959
                buf_pool->n_chunks++;
 
1960
        }
 
1961
 
 
1962
        buf_pool_mutex_exit(buf_pool);
 
1963
}
 
1964
 
 
1965
/********************************************************************//**
 
1966
Increase the buffer pool size. */
 
1967
static
 
1968
void
 
1969
buf_pool_increase(
 
1970
/*==============*/
 
1971
        ulint   change_size)
 
1972
{
 
1973
        ulint   i;
 
1974
 
 
1975
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1976
                buf_pool_increase_instance(
 
1977
                        buf_pool_from_array(i),
 
1978
                        change_size / srv_buf_pool_instances);
 
1979
        }
 
1980
 
 
1981
        buf_pool_set_sizes();
1442
1982
}
1443
1983
 
1444
1984
/********************************************************************//**
1448
1988
buf_pool_resize(void)
1449
1989
/*=================*/
1450
1990
{
1451
 
        buf_pool_mutex_enter();
1452
 
 
1453
 
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
1454
 
 
1455
 
                buf_pool_mutex_exit();
 
1991
        ulint   change_size;
 
1992
        ulint   min_change_size = 1048576 * srv_buf_pool_instances;
 
1993
 
 
1994
        buf_pool_mutex_enter_all();
 
1995
  
 
1996
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
 
1997
  
 
1998
                buf_pool_mutex_exit_all();
 
1999
 
 
2000
                return;
 
2001
 
 
2002
        } else if (srv_buf_pool_curr_size + min_change_size
 
2003
                   > srv_buf_pool_size) {
 
2004
  
 
2005
                change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
 
2006
                            / UNIV_PAGE_SIZE;
 
2007
 
 
2008
                buf_pool_mutex_exit_all();
 
2009
  
 
2010
                /* Disable adaptive hash indexes and empty the index
 
2011
                in order to free up memory in the buffer pool chunks. */
 
2012
                buf_pool_shrink(change_size);
 
2013
 
 
2014
        } else if (srv_buf_pool_curr_size + min_change_size
 
2015
                   < srv_buf_pool_size) {
 
2016
 
 
2017
                /* Enlarge the buffer pool by at least one megabyte */
 
2018
  
 
2019
                change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
 
2020
 
 
2021
                buf_pool_mutex_exit_all();
 
2022
 
 
2023
                buf_pool_increase(change_size);
 
2024
        } else {
 
2025
                srv_buf_pool_size = srv_buf_pool_old_size;
 
2026
 
 
2027
                buf_pool_mutex_exit_all();
 
2028
 
1456
2029
                return;
1457
2030
        }
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++;
 
2031
  
 
2032
        buf_pool_page_hash_rebuild();
 
2033
}
 
2034
 
 
2035
/****************************************************************//**
 
2036
Remove the sentinel block for the watch before replacing it with a real block.
 
2037
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
 
2038
the block has been replaced with the real block.
 
2039
@return reference count, to be added to the replacement block */
 
2040
static
 
2041
void
 
2042
buf_pool_watch_remove(
 
2043
/*==================*/
 
2044
        buf_pool_t*     buf_pool,       /*!< buffer pool instance */
 
2045
        ulint           fold,           /*!< in: buf_page_address_fold(
 
2046
                                        space, offset) */
 
2047
        buf_page_t*     watch)          /*!< in/out: sentinel for watch */
 
2048
{
 
2049
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2050
 
 
2051
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
 
2052
        ut_d(watch->in_page_hash = FALSE);
 
2053
        watch->buf_fix_count = 0;
 
2054
        watch->state = BUF_BLOCK_POOL_WATCH;
 
2055
}
 
2056
 
 
2057
/****************************************************************//**
 
2058
Stop watching if the page has been read in.
 
2059
buf_pool_watch_set(space,offset) must have returned NULL before. */
 
2060
UNIV_INTERN
 
2061
void
 
2062
buf_pool_watch_unset(
 
2063
/*=================*/
 
2064
        ulint   space,  /*!< in: space id */
 
2065
        ulint   offset) /*!< in: page number */
 
2066
{
 
2067
        buf_page_t*     bpage;
 
2068
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2069
        ulint           fold = buf_page_address_fold(space, offset);
 
2070
 
 
2071
        buf_pool_mutex_enter(buf_pool);
 
2072
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
2073
        /* The page must exist because buf_pool_watch_set()
 
2074
        increments buf_fix_count. */
 
2075
        ut_a(bpage);
 
2076
 
 
2077
        if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
 
2078
                mutex_t* mutex = buf_page_get_mutex(bpage);
 
2079
 
 
2080
                mutex_enter(mutex);
 
2081
                ut_a(bpage->buf_fix_count > 0);
 
2082
                bpage->buf_fix_count--;
 
2083
                mutex_exit(mutex);
 
2084
        } else {
 
2085
                ut_a(bpage->buf_fix_count > 0);
 
2086
 
 
2087
                if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
 
2088
                        buf_pool_watch_remove(buf_pool, fold, bpage);
1492
2089
                }
1493
 
 
1494
 
                srv_buf_pool_old_size = srv_buf_pool_size;
1495
 
                buf_pool_mutex_exit();
1496
2090
        }
1497
2091
 
1498
 
        buf_pool_page_hash_rebuild();
 
2092
        buf_pool_mutex_exit(buf_pool);
 
2093
}
 
2094
 
 
2095
/****************************************************************//**
 
2096
Check if the page has been read in.
 
2097
This may only be called after buf_pool_watch_set(space,offset)
 
2098
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
 
2099
@return FALSE if the given page was not read in, TRUE if it was */
 
2100
UNIV_INTERN
 
2101
ibool
 
2102
buf_pool_watch_occurred(
 
2103
/*====================*/
 
2104
        ulint   space,  /*!< in: space id */
 
2105
        ulint   offset) /*!< in: page number */
 
2106
{
 
2107
        ibool           ret;
 
2108
        buf_page_t*     bpage;
 
2109
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2110
        ulint           fold    = buf_page_address_fold(space, offset);
 
2111
 
 
2112
        buf_pool_mutex_enter(buf_pool);
 
2113
 
 
2114
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
2115
        /* The page must exist because buf_pool_watch_set()
 
2116
        increments buf_fix_count. */
 
2117
        ut_a(bpage);
 
2118
        ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
 
2119
        buf_pool_mutex_exit(buf_pool);
 
2120
 
 
2121
        return(ret);
1499
2122
}
1500
2123
 
1501
2124
/********************************************************************//**
1508
2131
/*================*/
1509
2132
        buf_page_t*     bpage)  /*!< in: buffer block of a file page */
1510
2133
{
1511
 
        buf_pool_mutex_enter();
 
2134
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
 
2135
 
 
2136
        buf_pool_mutex_enter(buf_pool);
1512
2137
 
1513
2138
        ut_a(buf_page_in_file(bpage));
1514
2139
 
1515
2140
        buf_LRU_make_block_young(bpage);
1516
2141
 
1517
 
        buf_pool_mutex_exit();
 
2142
        buf_pool_mutex_exit(buf_pool);
1518
2143
}
1519
2144
 
1520
2145
/********************************************************************//**
1532
2157
                                        read under mutex protection,
1533
2158
                                        or 0 if unknown */
1534
2159
{
1535
 
        ut_ad(!buf_pool_mutex_own());
 
2160
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
 
2161
 
 
2162
        ut_ad(!buf_pool_mutex_own(buf_pool));
1536
2163
        ut_a(buf_page_in_file(bpage));
1537
2164
 
1538
2165
        if (buf_page_peek_if_too_old(bpage)) {
1539
 
                buf_pool_mutex_enter();
 
2166
                buf_pool_mutex_enter(buf_pool);
1540
2167
                buf_LRU_make_block_young(bpage);
1541
 
                buf_pool_mutex_exit();
 
2168
                buf_pool_mutex_exit(buf_pool);
1542
2169
        } else if (!access_time) {
1543
2170
                ulint   time_ms = ut_time_ms();
1544
 
                buf_pool_mutex_enter();
 
2171
                buf_pool_mutex_enter(buf_pool);
1545
2172
                buf_page_set_accessed(bpage, time_ms);
1546
 
                buf_pool_mutex_exit();
 
2173
                buf_pool_mutex_exit(buf_pool);
1547
2174
        }
1548
2175
}
1549
2176
 
1558
2185
        ulint   offset) /*!< in: page number */
1559
2186
{
1560
2187
        buf_block_t*    block;
1561
 
 
1562
 
        buf_pool_mutex_enter();
1563
 
 
1564
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2188
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2189
 
 
2190
        buf_pool_mutex_enter(buf_pool);
 
2191
 
 
2192
        block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
1565
2193
 
1566
2194
        if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
 
2195
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
1567
2196
                block->check_index_page_at_flush = FALSE;
1568
2197
        }
1569
2198
 
1570
 
        buf_pool_mutex_exit();
 
2199
        buf_pool_mutex_exit(buf_pool);
1571
2200
}
1572
2201
 
1573
2202
/********************************************************************//**
1584
2213
{
1585
2214
        buf_block_t*    block;
1586
2215
        ibool           is_hashed;
1587
 
 
1588
 
        buf_pool_mutex_enter();
1589
 
 
1590
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2216
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2217
 
 
2218
        buf_pool_mutex_enter(buf_pool);
 
2219
 
 
2220
        block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
1591
2221
 
1592
2222
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
1593
2223
                is_hashed = FALSE;
1594
2224
        } else {
 
2225
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
1595
2226
                is_hashed = block->is_hashed;
1596
2227
        }
1597
2228
 
1598
 
        buf_pool_mutex_exit();
 
2229
        buf_pool_mutex_exit(buf_pool);
1599
2230
 
1600
2231
        return(is_hashed);
1601
2232
}
1615
2246
        ulint   offset) /*!< in: page number */
1616
2247
{
1617
2248
        buf_page_t*     bpage;
1618
 
 
1619
 
        buf_pool_mutex_enter();
1620
 
 
1621
 
        bpage = buf_page_hash_get(space, offset);
 
2249
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2250
 
 
2251
        buf_pool_mutex_enter(buf_pool);
 
2252
 
 
2253
        bpage = buf_page_hash_get(buf_pool, space, offset);
1622
2254
 
1623
2255
        if (bpage) {
 
2256
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1624
2257
                bpage->file_page_was_freed = TRUE;
1625
2258
        }
1626
2259
 
1627
 
        buf_pool_mutex_exit();
 
2260
        buf_pool_mutex_exit(buf_pool);
1628
2261
 
1629
2262
        return(bpage);
1630
2263
}
1643
2276
        ulint   offset) /*!< in: page number */
1644
2277
{
1645
2278
        buf_page_t*     bpage;
1646
 
 
1647
 
        buf_pool_mutex_enter();
1648
 
 
1649
 
        bpage = buf_page_hash_get(space, offset);
 
2279
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2280
 
 
2281
        buf_pool_mutex_enter(buf_pool);
 
2282
 
 
2283
        bpage = buf_page_hash_get(buf_pool, space, offset);
1650
2284
 
1651
2285
        if (bpage) {
 
2286
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1652
2287
                bpage->file_page_was_freed = FALSE;
1653
2288
        }
1654
2289
 
1655
 
        buf_pool_mutex_exit();
 
2290
        buf_pool_mutex_exit(buf_pool);
1656
2291
 
1657
2292
        return(bpage);
1658
2293
}
1679
2314
        mutex_t*        block_mutex;
1680
2315
        ibool           must_read;
1681
2316
        unsigned        access_time;
 
2317
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
1682
2318
 
1683
2319
#ifndef UNIV_LOG_DEBUG
1684
2320
        ut_ad(!ibuf_inside());
1686
2322
        buf_pool->stat.n_page_gets++;
1687
2323
 
1688
2324
        for (;;) {
1689
 
                buf_pool_mutex_enter();
 
2325
                buf_pool_mutex_enter(buf_pool);
1690
2326
lookup:
1691
 
                bpage = buf_page_hash_get(space, offset);
 
2327
                bpage = buf_page_hash_get(buf_pool, space, offset);
1692
2328
                if (bpage) {
 
2329
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1693
2330
                        break;
1694
2331
                }
1695
2332
 
1696
2333
                /* Page not in buf_pool: needs to be read from file */
1697
2334
 
1698
 
                buf_pool_mutex_exit();
 
2335
                buf_pool_mutex_exit(buf_pool);
1699
2336
 
1700
2337
                buf_read_page(space, zip_size, offset);
1701
2338
 
1707
2344
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
1708
2345
                /* There is no compressed page. */
1709
2346
err_exit:
1710
 
                buf_pool_mutex_exit();
 
2347
                buf_pool_mutex_exit(buf_pool);
1711
2348
                return(NULL);
1712
2349
        }
1713
2350
 
 
2351
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
 
2352
 
1714
2353
        switch (buf_page_get_state(bpage)) {
1715
2354
        case BUF_BLOCK_NOT_USED:
1716
2355
        case BUF_BLOCK_READY_FOR_USE:
1720
2359
                break;
1721
2360
        case BUF_BLOCK_ZIP_PAGE:
1722
2361
        case BUF_BLOCK_ZIP_DIRTY:
1723
 
                block_mutex = &buf_pool_zip_mutex;
 
2362
                block_mutex = &buf_pool->zip_mutex;
1724
2363
                mutex_enter(block_mutex);
1725
2364
                bpage->buf_fix_count++;
1726
2365
                goto got_block;
1748
2387
        must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
1749
2388
        access_time = buf_page_is_accessed(bpage);
1750
2389
 
1751
 
        buf_pool_mutex_exit();
 
2390
        buf_pool_mutex_exit(buf_pool);
1752
2391
 
1753
2392
        mutex_exit(block_mutex);
1754
2393
 
1878
2517
 
1879
2518
#ifndef UNIV_HOTBACKUP
1880
2519
/*******************************************************************//**
1881
 
Gets the block to whose frame the pointer is pointing to.
1882
 
@return pointer to block, never NULL */
1883
 
UNIV_INTERN
 
2520
Gets the block to whose frame the pointer is pointing to if found
 
2521
in this buffer pool instance.
 
2522
@return pointer to block */
 
2523
static
1884
2524
buf_block_t*
1885
 
buf_block_align(
1886
 
/*============*/
1887
 
        const byte*     ptr)    /*!< in: pointer to a frame */
 
2525
buf_block_align_instance(
 
2526
/*=====================*/
 
2527
        buf_pool_t*     buf_pool,       /*!< in: buffer in which the block
 
2528
                                        resides */
 
2529
        const byte*     ptr)            /*!< in: pointer to a frame */
1888
2530
{
1889
2531
        buf_chunk_t*    chunk;
1890
2532
        ulint           i;
1910
2552
                        ut_ad(block->frame == page_align(ptr));
1911
2553
#ifdef UNIV_DEBUG
1912
2554
                        /* A thread that updates these fields must
1913
 
                        hold buf_pool_mutex and block->mutex.  Acquire
 
2555
                        hold buf_pool->mutex and block->mutex.  Acquire
1914
2556
                        only the latter. */
1915
2557
                        mutex_enter(&block->mutex);
1916
2558
 
1959
2601
                }
1960
2602
        }
1961
2603
 
 
2604
        return(NULL);
 
2605
}
 
2606
 
 
2607
/*******************************************************************//**
 
2608
Gets the block to whose frame the pointer is pointing to.
 
2609
@return pointer to block, never NULL */
 
2610
UNIV_INTERN
 
2611
buf_block_t*
 
2612
buf_block_align(
 
2613
/*============*/
 
2614
        const byte*     ptr)    /*!< in: pointer to a frame */
 
2615
{
 
2616
        ulint           i;
 
2617
 
 
2618
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
2619
                buf_block_t*    block;
 
2620
 
 
2621
                block = buf_block_align_instance(
 
2622
                        buf_pool_from_array(i), ptr);
 
2623
                if (block) {
 
2624
                        return(block);
 
2625
                }
 
2626
        }
 
2627
 
1962
2628
        /* The block should always be found. */
1963
2629
        ut_error;
1964
2630
        return(NULL);
1966
2632
 
1967
2633
/********************************************************************//**
1968
2634
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
 
2635
the buf_block_t itself or a member of it. This functions checks one of
 
2636
the buffer pool instances.
1970
2637
@return TRUE if ptr belongs to a buf_block_t struct */
1971
 
UNIV_INTERN
 
2638
static
1972
2639
ibool
1973
 
buf_pointer_is_block_field(
1974
 
/*=======================*/
1975
 
        const void*             ptr)    /*!< in: pointer not
1976
 
                                        dereferenced */
 
2640
buf_pointer_is_block_field_instance(
 
2641
/*================================*/
 
2642
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
2643
        const void*     ptr)            /*!< in: pointer not dereferenced */
1977
2644
{
1978
2645
        const buf_chunk_t*              chunk   = buf_pool->chunks;
1979
2646
        const buf_chunk_t* const        echunk  = chunk + buf_pool->n_chunks;
1994
2661
}
1995
2662
 
1996
2663
/********************************************************************//**
 
2664
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
 
2665
the buf_block_t itself or a member of it
 
2666
@return TRUE if ptr belongs to a buf_block_t struct */
 
2667
UNIV_INTERN
 
2668
ibool
 
2669
buf_pointer_is_block_field(
 
2670
/*=======================*/
 
2671
        const void*     ptr)    /*!< in: pointer not dereferenced */
 
2672
{
 
2673
        ulint   i;
 
2674
 
 
2675
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
2676
                ibool   found;
 
2677
 
 
2678
                found = buf_pointer_is_block_field_instance(
 
2679
                        buf_pool_from_array(i), ptr);
 
2680
                if (found) {
 
2681
                        return(TRUE);
 
2682
                }
 
2683
        }
 
2684
 
 
2685
        return(FALSE);
 
2686
}
 
2687
 
 
2688
/********************************************************************//**
1997
2689
Find out if a buffer block was created by buf_chunk_init().
1998
2690
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
1999
2691
static
2000
2692
ibool
2001
2693
buf_block_is_uncompressed(
2002
2694
/*======================*/
2003
 
        const buf_block_t*      block)  /*!< in: pointer to block,
2004
 
                                        not dereferenced */
 
2695
        buf_pool_t*             buf_pool,       /*!< in: buffer pool instance */
 
2696
        const buf_block_t*      block)          /*!< in: pointer to block,
 
2697
                                                not dereferenced */
2005
2698
{
2006
 
        ut_ad(buf_pool_mutex_own());
 
2699
        ut_ad(buf_pool_mutex_own(buf_pool));
2007
2700
 
2008
2701
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2009
2702
                /* The pointer should be aligned. */
2010
2703
                return(FALSE);
2011
2704
        }
2012
2705
 
2013
 
        return(buf_pointer_is_block_field((void *)block));
 
2706
        return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
2014
2707
}
2015
2708
 
2016
2709
/********************************************************************//**
2027
2720
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2028
2721
        buf_block_t*    guess,  /*!< in: guessed block or NULL */
2029
2722
        ulint           mode,   /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2030
 
                                BUF_GET_NO_LATCH */
 
2723
                                BUF_GET_NO_LATCH, or
 
2724
                                BUF_GET_IF_IN_POOL_OR_WATCH */
2031
2725
        const char*     file,   /*!< in: file name */
2032
2726
        ulint           line,   /*!< in: line where called */
2033
2727
        mtr_t*          mtr)    /*!< in: mini-transaction */
2034
2728
{
2035
2729
        buf_block_t*    block;
 
2730
        ulint           fold;
2036
2731
        unsigned        access_time;
2037
2732
        ulint           fix_type;
2038
2733
        ibool           must_read;
2039
2734
        ulint           retries = 0;
 
2735
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2040
2736
 
2041
2737
        ut_ad(mtr);
2042
2738
        ut_ad(mtr->state == MTR_ACTIVE);
2044
2740
              || (rw_latch == RW_X_LATCH)
2045
2741
              || (rw_latch == RW_NO_LATCH));
2046
2742
        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));
 
2743
        ut_ad(mode == BUF_GET
 
2744
              || mode == BUF_GET_IF_IN_POOL
 
2745
              || mode == BUF_GET_NO_LATCH
 
2746
              || mode == BUF_GET_IF_IN_POOL_OR_WATCH);
2049
2747
        ut_ad(zip_size == fil_space_get_zip_size(space));
2050
2748
        ut_ad(ut_is_2pow(zip_size));
2051
2749
#ifndef UNIV_LOG_DEBUG
2052
2750
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2053
2751
#endif
2054
2752
        buf_pool->stat.n_page_gets++;
 
2753
        fold = buf_page_address_fold(space, offset);
2055
2754
loop:
2056
2755
        block = guess;
2057
 
        buf_pool_mutex_enter();
 
2756
        buf_pool_mutex_enter(buf_pool);
2058
2757
 
2059
2758
        if (block) {
2060
2759
                /* If the guess is a compressed page descriptor that
2065
2764
                the guess may be pointing to a buffer pool chunk that
2066
2765
                has been released when resizing the buffer pool. */
2067
2766
 
2068
 
                if (!buf_block_is_uncompressed(block)
 
2767
                if (!buf_block_is_uncompressed(buf_pool, block)
2069
2768
                    || offset != block->page.offset
2070
2769
                    || space != block->page.space
2071
2770
                    || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2078
2777
        }
2079
2778
 
2080
2779
        if (block == NULL) {
2081
 
                block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2780
                block = (buf_block_t*) buf_page_hash_get_low(
 
2781
                        buf_pool, space, offset, fold);
2082
2782
        }
2083
2783
 
2084
2784
loop2:
 
2785
        if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
 
2786
                block = NULL;
 
2787
        }
 
2788
 
2085
2789
        if (block == NULL) {
2086
2790
                /* Page not in buf_pool: needs to be read from file */
2087
2791
 
2088
 
                buf_pool_mutex_exit();
2089
 
 
2090
 
                if (mode == BUF_GET_IF_IN_POOL) {
 
2792
                if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
 
2793
                        block = (buf_block_t*) buf_pool_watch_set(
 
2794
                                space, offset, fold);
 
2795
 
 
2796
                        if (UNIV_LIKELY_NULL(block)) {
 
2797
 
 
2798
                                goto got_block;
 
2799
                        }
 
2800
                }
 
2801
 
 
2802
                buf_pool_mutex_exit(buf_pool);
 
2803
 
 
2804
                if (mode == BUF_GET_IF_IN_POOL
 
2805
                    || mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2091
2806
 
2092
2807
                        return(NULL);
2093
2808
                }
2122
2837
                goto loop;
2123
2838
        }
2124
2839
 
 
2840
got_block:
2125
2841
        ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
2126
2842
 
2127
2843
        must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
2128
2844
 
2129
2845
        if (must_read && mode == BUF_GET_IF_IN_POOL) {
2130
 
                /* The page is only being read to buffer */
2131
 
                buf_pool_mutex_exit();
 
2846
 
 
2847
                /* The page is being read to buffer pool,
 
2848
                but we cannot wait around for the read to
 
2849
                complete. */
 
2850
                buf_pool_mutex_exit(buf_pool);
2132
2851
 
2133
2852
                return(NULL);
2134
2853
        }
2144
2863
        case BUF_BLOCK_ZIP_DIRTY:
2145
2864
                bpage = &block->page;
2146
2865
                /* Protect bpage->buf_fix_count. */
2147
 
                mutex_enter(&buf_pool_zip_mutex);
 
2866
                mutex_enter(&buf_pool->zip_mutex);
2148
2867
 
2149
2868
                if (bpage->buf_fix_count
2150
2869
                    || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2151
2870
                        /* This condition often occurs when the buffer
2152
2871
                        is not buffer-fixed, but I/O-fixed by
2153
2872
                        buf_page_init_for_read(). */
2154
 
                        mutex_exit(&buf_pool_zip_mutex);
 
2873
                        mutex_exit(&buf_pool->zip_mutex);
2155
2874
wait_until_unfixed:
2156
2875
                        /* The block is buffer-fixed or I/O-fixed.
2157
2876
                        Try again later. */
2158
 
                        buf_pool_mutex_exit();
 
2877
                        buf_pool_mutex_exit(buf_pool);
2159
2878
                        os_thread_sleep(WAIT_FOR_READ);
2160
 
 
 
2879
  
2161
2880
                        goto loop;
2162
2881
                }
2163
2882
 
2164
2883
                /* Allocate an uncompressed page. */
2165
 
                buf_pool_mutex_exit();
2166
 
                mutex_exit(&buf_pool_zip_mutex);
 
2884
                buf_pool_mutex_exit(buf_pool);
 
2885
                mutex_exit(&buf_pool->zip_mutex);
2167
2886
 
2168
 
                block = buf_LRU_get_free_block(0);
 
2887
                block = buf_LRU_get_free_block(buf_pool, 0);
2169
2888
                ut_a(block);
2170
2889
 
2171
 
                buf_pool_mutex_enter();
 
2890
                buf_pool_mutex_enter(buf_pool);
2172
2891
                mutex_enter(&block->mutex);
2173
2892
 
2174
2893
                {
2175
 
                        buf_page_t*     hash_bpage
2176
 
                                = buf_page_hash_get(space, offset);
 
2894
                        buf_page_t*     hash_bpage;
 
2895
 
 
2896
                        hash_bpage = buf_page_hash_get_low(
 
2897
                                buf_pool, space, offset, fold);
2177
2898
 
2178
2899
                        if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2179
2900
                                /* The buf_pool->page_hash was modified
2180
 
                                while buf_pool_mutex was released.
 
2901
                                while buf_pool->mutex was released.
2181
2902
                                Free the block that was allocated. */
2182
2903
 
2183
2904
                                buf_LRU_block_free_non_file_page(block);
2193
2914
                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
2194
2915
 
2195
2916
                        /* The block was buffer-fixed or I/O-fixed
2196
 
                        while buf_pool_mutex was not held by this thread.
 
2917
                        while buf_pool->mutex was not held by this thread.
2197
2918
                        Free the block that was allocated and try again.
2198
2919
                        This should be extremely unlikely. */
2199
2920
 
2206
2927
                /* Move the compressed page from bpage to block,
2207
2928
                and uncompress it. */
2208
2929
 
2209
 
                mutex_enter(&buf_pool_zip_mutex);
 
2930
                mutex_enter(&buf_pool->zip_mutex);
2210
2931
 
2211
2932
                buf_relocate(bpage, &block->page);
2212
2933
                buf_block_init_low(block);
2236
2957
 
2237
2958
                block->page.buf_fix_count = 1;
2238
2959
                buf_block_set_io_fix(block, BUF_IO_READ);
2239
 
                rw_lock_x_lock(&block->lock);
 
2960
                rw_lock_x_lock_func(&block->lock, 0, file, line);
2240
2961
 
2241
2962
                UNIV_MEM_INVALID(bpage, sizeof *bpage);
2242
2963
 
2243
2964
                mutex_exit(&block->mutex);
2244
 
                mutex_exit(&buf_pool_zip_mutex);
 
2965
                mutex_exit(&buf_pool->zip_mutex);
2245
2966
                buf_pool->n_pend_unzip++;
2246
2967
 
2247
 
                buf_buddy_free(bpage, sizeof *bpage);
 
2968
                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
2248
2969
 
2249
 
                buf_pool_mutex_exit();
 
2970
                buf_pool_mutex_exit(buf_pool);
2250
2971
 
2251
2972
                /* Decompress the page and apply buffered operations
2252
 
                while not holding buf_pool_mutex or block->mutex. */
 
2973
                while not holding buf_pool->mutex or block->mutex. */
2253
2974
                success = buf_zip_decompress(block, srv_use_checksums);
2254
2975
                ut_a(success);
2255
2976
 
2259
2980
                }
2260
2981
 
2261
2982
                /* Unfix and unlatch the block. */
2262
 
                buf_pool_mutex_enter();
 
2983
                buf_pool_mutex_enter(buf_pool);
2263
2984
                mutex_enter(&block->mutex);
2264
2985
                block->page.buf_fix_count--;
2265
2986
                buf_block_set_io_fix(block, BUF_IO_NONE);
2266
2987
                mutex_exit(&block->mutex);
2267
2988
                buf_pool->n_pend_unzip--;
2268
2989
                rw_lock_x_unlock(&block->lock);
 
2990
 
2269
2991
                break;
2270
2992
 
2271
2993
        case BUF_BLOCK_ZIP_FREE:
2295
3017
 
2296
3018
        access_time = buf_page_is_accessed(&block->page);
2297
3019
 
2298
 
        buf_pool_mutex_exit();
 
3020
        buf_pool_mutex_exit(buf_pool);
2299
3021
 
2300
3022
        buf_page_set_accessed_make_young(&block->page, access_time);
2301
3023
 
2380
3102
        ulint           line,   /*!< in: line where called */
2381
3103
        mtr_t*          mtr)    /*!< in: mini-transaction */
2382
3104
{
 
3105
        buf_pool_t*     buf_pool;
2383
3106
        unsigned        access_time;
2384
3107
        ibool           success;
2385
3108
        ulint           fix_type;
2473
3196
        ut_a(ibuf_count_get(buf_block_get_space(block),
2474
3197
                            buf_block_get_page_no(block)) == 0);
2475
3198
#endif
 
3199
        buf_pool = buf_pool_from_block(block);
2476
3200
        buf_pool->stat.n_page_gets++;
2477
3201
 
2478
3202
        return(TRUE);
2494
3218
        ulint           line,   /*!< in: line where called */
2495
3219
        mtr_t*          mtr)    /*!< in: mini-transaction */
2496
3220
{
 
3221
        buf_pool_t*     buf_pool;
2497
3222
        ibool           success;
2498
3223
        ulint           fix_type;
2499
3224
 
2522
3247
 
2523
3248
        mutex_exit(&block->mutex);
2524
3249
 
 
3250
        buf_pool = buf_pool_from_block(block);
 
3251
 
2525
3252
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
2526
 
                buf_pool_mutex_enter();
 
3253
                buf_pool_mutex_enter(buf_pool);
2527
3254
                buf_LRU_make_block_young(&block->page);
2528
 
                buf_pool_mutex_exit();
 
3255
                buf_pool_mutex_exit(buf_pool);
2529
3256
        } else if (!buf_page_is_accessed(&block->page)) {
2530
3257
                /* Above, we do a dirty read on purpose, to avoid
2531
3258
                mutex contention.  The field buf_page_t::access_time
2533
3260
                field must be protected by mutex, however. */
2534
3261
                ulint   time_ms = ut_time_ms();
2535
3262
 
2536
 
                buf_pool_mutex_enter();
 
3263
                buf_pool_mutex_enter(buf_pool);
2537
3264
                buf_page_set_accessed(&block->page, time_ms);
2538
 
                buf_pool_mutex_exit();
 
3265
                buf_pool_mutex_exit(buf_pool);
2539
3266
        }
2540
3267
 
2541
3268
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
2597
3324
        buf_block_t*    block;
2598
3325
        ibool           success;
2599
3326
        ulint           fix_type;
 
3327
        buf_pool_t*     buf_pool = buf_pool_get(space_id, page_no);
2600
3328
 
2601
3329
        ut_ad(mtr);
2602
3330
        ut_ad(mtr->state == MTR_ACTIVE);
2603
3331
 
2604
 
        buf_pool_mutex_enter();
2605
 
        block = buf_block_hash_get(space_id, page_no);
 
3332
        buf_pool_mutex_enter(buf_pool);
 
3333
        block = buf_block_hash_get(buf_pool, space_id, page_no);
2606
3334
 
2607
 
        if (!block) {
2608
 
                buf_pool_mutex_exit();
 
3335
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
 
3336
                buf_pool_mutex_exit(buf_pool);
2609
3337
                return(NULL);
2610
3338
        }
2611
3339
 
 
3340
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
 
3341
 
2612
3342
        mutex_enter(&block->mutex);
2613
 
        buf_pool_mutex_exit();
 
3343
        buf_pool_mutex_exit(buf_pool);
2614
3344
 
2615
3345
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2616
3346
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2693
3423
        ulint           space,  /*!< in: space id */
2694
3424
        ulint           offset, /*!< in: offset of the page within space
2695
3425
                                in units of a page */
 
3426
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
2696
3427
        buf_block_t*    block)  /*!< in: block to init */
2697
3428
{
2698
3429
        buf_page_t*     hash_page;
 
3430
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2699
3431
 
2700
 
        ut_ad(buf_pool_mutex_own());
 
3432
        ut_ad(buf_pool_mutex_own(buf_pool));
2701
3433
        ut_ad(mutex_own(&(block->mutex)));
2702
3434
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
2703
3435
 
2715
3447
 
2716
3448
        buf_block_init_low(block);
2717
3449
 
2718
 
        block->lock_hash_val    = lock_rec_hash(space, offset);
 
3450
        block->lock_hash_val = lock_rec_hash(space, offset);
 
3451
 
 
3452
        buf_page_init_low(&block->page);
2719
3453
 
2720
3454
        /* Insert into the hash table of file pages */
2721
3455
 
2722
 
        hash_page = buf_page_hash_get(space, offset);
2723
 
 
2724
 
        if (UNIV_LIKELY_NULL(hash_page)) {
 
3456
        hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
3457
 
 
3458
        if (UNIV_LIKELY(!hash_page)) {
 
3459
        } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
 
3460
                /* Preserve the reference count. */
 
3461
                ulint   buf_fix_count = hash_page->buf_fix_count;
 
3462
 
 
3463
                ut_a(buf_fix_count > 0);
 
3464
                block->page.buf_fix_count += buf_fix_count;
 
3465
                buf_pool_watch_remove(buf_pool, fold, hash_page);
 
3466
        } else {
2725
3467
                fprintf(stderr,
2726
3468
                        "InnoDB: Error: page %lu %lu already found"
2727
3469
                        " in the hash table: %p, %p\n",
2730
3472
                        (const void*) hash_page, (const void*) block);
2731
3473
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2732
3474
                mutex_exit(&block->mutex);
2733
 
                buf_pool_mutex_exit();
 
3475
                buf_pool_mutex_exit(buf_pool);
2734
3476
                buf_print();
2735
3477
                buf_LRU_print();
2736
3478
                buf_validate();
2739
3481
                ut_error;
2740
3482
        }
2741
3483
 
2742
 
        buf_page_init_low(&block->page);
2743
 
 
2744
3484
        ut_ad(!block->page.in_zip_hash);
2745
3485
        ut_ad(!block->page.in_page_hash);
2746
3486
        ut_d(block->page.in_page_hash = TRUE);
2747
3487
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2748
 
                    buf_page_address_fold(space, offset), &block->page);
 
3488
                    fold, &block->page);
2749
3489
}
2750
3490
 
2751
3491
/********************************************************************//**
2767
3507
        ulint           space,  /*!< in: space id */
2768
3508
        ulint           zip_size,/*!< in: compressed page size, or 0 */
2769
3509
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
2770
 
        ib_int64_t      tablespace_version,/*!< in: prevents reading from a wrong
 
3510
        ib_int64_t      tablespace_version,
 
3511
                                /*!< in: prevents reading from a wrong
2771
3512
                                version of the tablespace in case we have done
2772
3513
                                DISCARD + IMPORT */
2773
3514
        ulint           offset) /*!< in: page number */
2774
3515
{
2775
3516
        buf_block_t*    block;
2776
 
        buf_page_t*     bpage;
 
3517
        buf_page_t*     bpage   = NULL;
 
3518
        buf_page_t*     watch_page;
2777
3519
        mtr_t           mtr;
 
3520
        ulint           fold;
2778
3521
        ibool           lru     = FALSE;
2779
3522
        void*           data;
 
3523
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2780
3524
 
2781
3525
        ut_ad(buf_pool);
2782
3526
 
2805
3549
            && UNIV_LIKELY(!recv_recovery_is_on())) {
2806
3550
                block = NULL;
2807
3551
        } else {
2808
 
                block = buf_LRU_get_free_block(0);
 
3552
                block = buf_LRU_get_free_block(buf_pool, 0);
2809
3553
                ut_ad(block);
 
3554
                ut_ad(buf_pool_from_block(block) == buf_pool);
2810
3555
        }
2811
3556
 
2812
 
        buf_pool_mutex_enter();
2813
 
 
2814
 
        if (buf_page_hash_get(space, offset)) {
 
3557
        fold = buf_page_address_fold(space, offset);
 
3558
 
 
3559
        buf_pool_mutex_enter(buf_pool);
 
3560
 
 
3561
        watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
3562
        if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
2815
3563
                /* The page is already in the buffer pool. */
 
3564
                watch_page = NULL;
2816
3565
err_exit:
2817
3566
                if (block) {
2818
3567
                        mutex_enter(&block->mutex);
2836
3585
        if (block) {
2837
3586
                bpage = &block->page;
2838
3587
                mutex_enter(&block->mutex);
2839
 
                buf_page_init(space, offset, block);
 
3588
 
 
3589
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
 
3590
 
 
3591
                buf_page_init(space, offset, fold, block);
2840
3592
 
2841
3593
                /* The block must be put to the LRU list, to the old blocks */
2842
3594
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2856
3608
                if (UNIV_UNLIKELY(zip_size)) {
2857
3609
                        page_zip_set_size(&block->page.zip, zip_size);
2858
3610
 
2859
 
                        /* buf_pool_mutex may be released and
 
3611
                        /* buf_pool->mutex may be released and
2860
3612
                        reacquired by buf_buddy_alloc().  Thus, we
2861
3613
                        must release block->mutex in order not to
2862
3614
                        break the latching order in the reacquisition
2863
 
                        of buf_pool_mutex.  We also must defer this
 
3615
                        of buf_pool->mutex.  We also must defer this
2864
3616
                        operation until after the block descriptor has
2865
3617
                        been added to buf_pool->LRU and
2866
3618
                        buf_pool->page_hash. */
2867
3619
                        mutex_exit(&block->mutex);
2868
 
                        data = buf_buddy_alloc(zip_size, &lru);
 
3620
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
2869
3621
                        mutex_enter(&block->mutex);
2870
3622
                        block->page.zip.data = data;
2871
3623
 
2889
3641
                control block (bpage), in order to avoid the
2890
3642
                invocation of buf_buddy_relocate_block() on
2891
3643
                uninitialized data. */
2892
 
                data = buf_buddy_alloc(zip_size, &lru);
2893
 
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
 
3644
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
3645
                bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
 
3646
 
 
3647
                /* Initialize the buf_pool pointer. */
 
3648
                bpage->buf_pool = buf_pool;
2894
3649
 
2895
3650
                /* If buf_buddy_alloc() allocated storage from the LRU list,
2896
 
                it released and reacquired buf_pool_mutex.  Thus, we must
 
3651
                it released and reacquired buf_pool->mutex.  Thus, we must
2897
3652
                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;
 
3653
                if (UNIV_UNLIKELY(lru)) {
 
3654
 
 
3655
                        watch_page = buf_page_hash_get_low(
 
3656
                                buf_pool, space, offset, fold);
 
3657
 
 
3658
                        if (watch_page
 
3659
                            && !buf_pool_watch_is_sentinel(buf_pool,
 
3660
                                                           watch_page)) {
 
3661
 
 
3662
                                /* The block was added by some other thread. */
 
3663
                                watch_page = NULL;
 
3664
                                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 
3665
                                buf_buddy_free(buf_pool, data, zip_size);
 
3666
 
 
3667
                                bpage = NULL;
 
3668
                                goto func_exit;
 
3669
                        }
2907
3670
                }
2908
3671
 
2909
3672
                page_zip_des_init(&bpage->zip);
2910
3673
                page_zip_set_size(&bpage->zip, zip_size);
2911
3674
                bpage->zip.data = data;
2912
3675
 
2913
 
                mutex_enter(&buf_pool_zip_mutex);
 
3676
                mutex_enter(&buf_pool->zip_mutex);
2914
3677
                UNIV_MEM_DESC(bpage->zip.data,
2915
3678
                              page_zip_get_size(&bpage->zip), bpage);
 
3679
 
2916
3680
                buf_page_init_low(bpage);
 
3681
 
2917
3682
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
2918
3683
                bpage->space    = space;
2919
3684
                bpage->offset   = offset;
2920
3685
 
 
3686
 
2921
3687
#ifdef UNIV_DEBUG
2922
3688
                bpage->in_page_hash = FALSE;
2923
3689
                bpage->in_zip_hash = FALSE;
2927
3693
#endif /* UNIV_DEBUG */
2928
3694
 
2929
3695
                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);
 
3696
 
 
3697
                if (UNIV_LIKELY_NULL(watch_page)) {
 
3698
                        /* Preserve the reference count. */
 
3699
                        ulint   buf_fix_count = watch_page->buf_fix_count;
 
3700
                        ut_a(buf_fix_count > 0);
 
3701
                        bpage->buf_fix_count += buf_fix_count;
 
3702
                        ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
 
3703
                        buf_pool_watch_remove(buf_pool, fold, watch_page);
 
3704
                }
 
3705
 
 
3706
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
 
3707
                            bpage);
2932
3708
 
2933
3709
                /* The block must be put to the LRU list, to the old blocks */
2934
3710
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2936
3712
 
2937
3713
                buf_page_set_io_fix(bpage, BUF_IO_READ);
2938
3714
 
2939
 
                mutex_exit(&buf_pool_zip_mutex);
 
3715
                mutex_exit(&buf_pool->zip_mutex);
2940
3716
        }
2941
3717
 
2942
3718
        buf_pool->n_pend_reads++;
2943
3719
func_exit:
2944
 
        buf_pool_mutex_exit();
 
3720
        buf_pool_mutex_exit(buf_pool);
2945
3721
 
2946
3722
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
2947
3723
 
2970
3746
{
2971
3747
        buf_frame_t*    frame;
2972
3748
        buf_block_t*    block;
 
3749
        ulint           fold;
2973
3750
        buf_block_t*    free_block      = NULL;
2974
3751
        ulint           time_ms         = ut_time_ms();
 
3752
        buf_pool_t*     buf_pool        = buf_pool_get(space, offset);
2975
3753
 
2976
3754
        ut_ad(mtr);
2977
3755
        ut_ad(mtr->state == MTR_ACTIVE);
2978
3756
        ut_ad(space || !zip_size);
2979
3757
 
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)) {
 
3758
        free_block = buf_LRU_get_free_block(buf_pool, 0);
 
3759
 
 
3760
        fold = buf_page_address_fold(space, offset);
 
3761
 
 
3762
        buf_pool_mutex_enter(buf_pool);
 
3763
 
 
3764
        block = (buf_block_t*) buf_page_hash_get_low(
 
3765
                buf_pool, space, offset, fold);
 
3766
 
 
3767
        if (block
 
3768
            && buf_page_in_file(&block->page)
 
3769
            && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2987
3770
#ifdef UNIV_IBUF_COUNT_DEBUG
2988
3771
                ut_a(ibuf_count_get(space, offset) == 0);
2989
3772
#endif
2992
3775
#endif /* UNIV_DEBUG_FILE_ACCESSES */
2993
3776
 
2994
3777
                /* Page can be found in buf_pool */
2995
 
                buf_pool_mutex_exit();
 
3778
                buf_pool_mutex_exit(buf_pool);
2996
3779
 
2997
3780
                buf_block_free(free_block);
2998
3781
 
3013
3796
 
3014
3797
        mutex_enter(&block->mutex);
3015
3798
 
3016
 
        buf_page_init(space, offset, block);
 
3799
        buf_page_init(space, offset, fold, block);
3017
3800
 
3018
3801
        /* The block must be put to the LRU list */
3019
3802
        buf_LRU_add_block(&block->page, FALSE);
3026
3809
                ibool   lru;
3027
3810
 
3028
3811
                /* Prevent race conditions during buf_buddy_alloc(),
3029
 
                which may release and reacquire buf_pool_mutex,
 
3812
                which may release and reacquire buf_pool->mutex,
3030
3813
                by IO-fixing and X-latching the block. */
3031
3814
 
3032
3815
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3034
3817
 
3035
3818
                page_zip_set_size(&block->page.zip, zip_size);
3036
3819
                mutex_exit(&block->mutex);
3037
 
                /* buf_pool_mutex may be released and reacquired by
 
3820
                /* buf_pool->mutex may be released and reacquired by
3038
3821
                buf_buddy_alloc().  Thus, we must release block->mutex
3039
3822
                in order not to break the latching order in
3040
 
                the reacquisition of buf_pool_mutex.  We also must
 
3823
                the reacquisition of buf_pool->mutex.  We also must
3041
3824
                defer this operation until after the block descriptor
3042
3825
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3043
 
                data = buf_buddy_alloc(zip_size, &lru);
 
3826
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3044
3827
                mutex_enter(&block->mutex);
3045
3828
                block->page.zip.data = data;
3046
3829
 
3058
3841
 
3059
3842
        buf_page_set_accessed(&block->page, time_ms);
3060
3843
 
3061
 
        buf_pool_mutex_exit();
 
3844
        buf_pool_mutex_exit(buf_pool);
3062
3845
 
3063
3846
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3064
3847
 
3070
3853
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3071
3854
 
3072
3855
        /* Flush pages from the end of the LRU list if necessary */
3073
 
        buf_flush_free_margin();
 
3856
        buf_flush_free_margin(buf_pool);
3074
3857
 
3075
3858
        frame = block->frame;
3076
3859
 
3106
3889
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
3107
3890
{
3108
3891
        enum buf_io_fix io_type;
 
3892
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3109
3893
        const ibool     uncompressed = (buf_page_get_state(bpage)
3110
3894
                                        == BUF_BLOCK_FILE_PAGE);
3111
3895
 
3241
4025
                }
3242
4026
        }
3243
4027
 
3244
 
        buf_pool_mutex_enter();
 
4028
        buf_pool_mutex_enter(buf_pool);
3245
4029
        mutex_enter(buf_page_get_mutex(bpage));
3246
4030
 
3247
4031
#ifdef UNIV_IBUF_COUNT_DEBUG
3305
4089
#endif /* UNIV_DEBUG */
3306
4090
 
3307
4091
        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
 
4092
        buf_pool_mutex_exit(buf_pool);
 
4093
}
 
4094
 
 
4095
/*********************************************************************//**
 
4096
Asserts that all file pages in the buffer are in a replaceable state.
 
4097
@return TRUE */
 
4098
static
 
4099
ibool
 
4100
buf_all_freed_instance(
 
4101
/*===================*/
 
4102
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instancce */
 
4103
{
 
4104
        ulint           i;
 
4105
        buf_chunk_t*    chunk;
 
4106
 
 
4107
        ut_ad(buf_pool);
 
4108
 
 
4109
        buf_pool_mutex_enter(buf_pool);
 
4110
 
 
4111
        chunk = buf_pool->chunks;
 
4112
 
 
4113
        for (i = buf_pool->n_chunks; i--; chunk++) {
 
4114
 
 
4115
                const buf_block_t* block = buf_chunk_not_freed(chunk);
 
4116
 
 
4117
                if (UNIV_LIKELY_NULL(block)) {
 
4118
                        fprintf(stderr,
 
4119
                                "Page %lu %lu still fixed or dirty\n",
 
4120
                                (ulong) block->page.space,
 
4121
                                (ulong) block->page.offset);
 
4122
                        ut_error;
 
4123
                }
 
4124
        }
 
4125
 
 
4126
        buf_pool_mutex_exit(buf_pool);
 
4127
 
 
4128
        return(TRUE);
 
4129
}
 
4130
 
 
4131
/*********************************************************************//**
 
4132
Invalidates file pages in one buffer pool instance */
 
4133
static
3316
4134
void
3317
 
buf_pool_invalidate(void)
3318
 
/*=====================*/
 
4135
buf_pool_invalidate_instance(
 
4136
/*=========================*/
 
4137
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3319
4138
{
3320
4139
        ibool           freed;
3321
4140
        enum buf_flush  i;
3322
4141
 
3323
 
        buf_pool_mutex_enter();
 
4142
        buf_pool_mutex_enter(buf_pool);
3324
4143
 
3325
4144
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
3326
4145
 
3336
4155
                pool invalidation to proceed we must ensure there is NO
3337
4156
                write activity happening. */
3338
4157
                if (buf_pool->n_flush[i] > 0) {
3339
 
                        buf_pool_mutex_exit();
3340
 
                        buf_flush_wait_batch_end(i);
3341
 
                        buf_pool_mutex_enter();
 
4158
                        buf_pool_mutex_exit(buf_pool);
 
4159
                        buf_flush_wait_batch_end(buf_pool, i);
 
4160
                        buf_pool_mutex_enter(buf_pool);
3342
4161
                }
3343
4162
        }
3344
4163
 
3345
 
        buf_pool_mutex_exit();
 
4164
        buf_pool_mutex_exit(buf_pool);
3346
4165
 
3347
 
        ut_ad(buf_all_freed());
 
4166
        ut_ad(buf_all_freed_instance(buf_pool));
3348
4167
 
3349
4168
        freed = TRUE;
3350
4169
 
3351
4170
        while (freed) {
3352
 
                freed = buf_LRU_search_and_free_block(100);
 
4171
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
3353
4172
        }
3354
4173
 
3355
 
        buf_pool_mutex_enter();
 
4174
        buf_pool_mutex_enter(buf_pool);
3356
4175
 
3357
4176
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
3358
4177
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
3363
4182
        buf_pool->LRU_flush_ended = 0;
3364
4183
 
3365
4184
        memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
3366
 
        buf_refresh_io_stats();
3367
 
 
3368
 
        buf_pool_mutex_exit();
 
4185
        buf_refresh_io_stats(buf_pool);
 
4186
 
 
4187
        buf_pool_mutex_exit(buf_pool);
 
4188
}
 
4189
 
 
4190
/*********************************************************************//**
 
4191
Invalidates the file pages in the buffer pool when an archive recovery is
 
4192
completed. All the file pages buffered must be in a replaceable state when
 
4193
this function is called: not latched and not modified. */
 
4194
UNIV_INTERN
 
4195
void
 
4196
buf_pool_invalidate(void)
 
4197
/*=====================*/
 
4198
{
 
4199
        ulint   i;
 
4200
 
 
4201
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4202
                buf_pool_invalidate_instance(buf_pool_from_array(i));
 
4203
        }
3369
4204
}
3370
4205
 
3371
4206
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3372
4207
/*********************************************************************//**
3373
 
Validates the buffer buf_pool data structure.
 
4208
Validates data in one buffer pool instance
3374
4209
@return TRUE */
3375
 
UNIV_INTERN
 
4210
static
3376
4211
ibool
3377
 
buf_validate(void)
3378
 
/*==============*/
 
4212
buf_pool_validate_instance(
 
4213
/*=======================*/
 
4214
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3379
4215
{
3380
4216
        buf_page_t*     b;
3381
4217
        buf_chunk_t*    chunk;
3390
4226
 
3391
4227
        ut_ad(buf_pool);
3392
4228
 
3393
 
        buf_pool_mutex_enter();
 
4229
        buf_pool_mutex_enter(buf_pool);
3394
4230
 
3395
4231
        chunk = buf_pool->chunks;
3396
4232
 
3415
4251
                                break;
3416
4252
 
3417
4253
                        case BUF_BLOCK_FILE_PAGE:
3418
 
                                ut_a(buf_page_hash_get(buf_block_get_space(
 
4254
                                ut_a(buf_page_hash_get(buf_pool,
 
4255
                                                       buf_block_get_space(
3419
4256
                                                               block),
3420
4257
                                                       buf_block_get_page_no(
3421
4258
                                                               block))
3462
4299
                                }
3463
4300
 
3464
4301
                                n_lru++;
3465
 
 
3466
 
                                if (block->page.oldest_modification > 0) {
3467
 
                                        n_flush++;
3468
 
                                }
3469
 
 
3470
4302
                                break;
3471
4303
 
3472
4304
                        case BUF_BLOCK_NOT_USED:
3484
4316
                }
3485
4317
        }
3486
4318
 
3487
 
        mutex_enter(&buf_pool_zip_mutex);
 
4319
        mutex_enter(&buf_pool->zip_mutex);
3488
4320
 
3489
4321
        /* Check clean compressed-only blocks. */
3490
4322
 
3505
4337
                        ut_error;
3506
4338
                        break;
3507
4339
                }
 
4340
 
 
4341
                /* It is OK to read oldest_modification here because
 
4342
                we have acquired buf_pool->zip_mutex above which acts
 
4343
                as the 'block->mutex' for these bpages. */
3508
4344
                ut_a(!b->oldest_modification);
3509
 
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
 
4345
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3510
4346
 
3511
4347
                n_lru++;
3512
4348
                n_zip++;
3513
4349
        }
3514
4350
 
3515
 
        /* Check dirty compressed-only blocks. */
 
4351
        /* Check dirty blocks. */
3516
4352
 
 
4353
        buf_flush_list_mutex_enter(buf_pool);
3517
4354
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
3518
4355
             b = UT_LIST_GET_NEXT(list, b)) {
3519
4356
                ut_ad(b->in_flush_list);
 
4357
                ut_a(b->oldest_modification);
 
4358
                n_flush++;
3520
4359
 
3521
4360
                switch (buf_page_get_state(b)) {
3522
4361
                case BUF_BLOCK_ZIP_DIRTY:
3523
 
                        ut_a(b->oldest_modification);
3524
4362
                        n_lru++;
3525
 
                        n_flush++;
3526
4363
                        n_zip++;
3527
4364
                        switch (buf_page_get_io_fix(b)) {
3528
4365
                        case BUF_IO_NONE:
3529
4366
                        case BUF_IO_READ:
3530
4367
                                break;
3531
 
 
3532
4368
                        case BUF_IO_WRITE:
3533
4369
                                switch (buf_page_get_flush_type(b)) {
3534
4370
                                case BUF_FLUSH_LRU:
3558
4394
                        ut_error;
3559
4395
                        break;
3560
4396
                }
3561
 
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
 
4397
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3562
4398
        }
3563
4399
 
3564
 
        mutex_exit(&buf_pool_zip_mutex);
 
4400
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
 
4401
 
 
4402
        buf_flush_list_mutex_exit(buf_pool);
 
4403
 
 
4404
        mutex_exit(&buf_pool->zip_mutex);
3565
4405
 
3566
4406
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
3567
4407
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
3577
4417
                        (ulong) n_free);
3578
4418
                ut_error;
3579
4419
        }
3580
 
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
3581
4420
 
3582
4421
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
3583
4422
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
3584
4423
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
3585
4424
 
3586
 
        buf_pool_mutex_exit();
 
4425
        buf_pool_mutex_exit(buf_pool);
3587
4426
 
3588
4427
        ut_a(buf_LRU_validate());
3589
 
        ut_a(buf_flush_validate());
3590
 
 
3591
 
        return(TRUE);
3592
 
}
 
4428
        ut_a(buf_flush_validate(buf_pool));
 
4429
 
 
4430
        return(TRUE);
 
4431
}
 
4432
 
 
4433
/*********************************************************************//**
 
4434
Validates the buffer buf_pool data structure.
 
4435
@return TRUE */
 
4436
UNIV_INTERN
 
4437
ibool
 
4438
buf_validate(void)
 
4439
/*==============*/
 
4440
{
 
4441
        ulint   i;
 
4442
 
 
4443
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4444
                buf_pool_t*     buf_pool;
 
4445
 
 
4446
                buf_pool = buf_pool_from_array(i);
 
4447
 
 
4448
                buf_pool_validate_instance(buf_pool);
 
4449
        }
 
4450
        return(TRUE);
 
4451
}
 
4452
 
3593
4453
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3594
4454
 
3595
4455
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3596
4456
/*********************************************************************//**
3597
 
Prints info of the buffer buf_pool data structure. */
3598
 
UNIV_INTERN
 
4457
Prints info of the buffer buf_pool data structure for one instance. */
 
4458
static
3599
4459
void
3600
 
buf_print(void)
3601
 
/*===========*/
 
4460
buf_print_instance(
 
4461
/*===============*/
 
4462
        buf_pool_t*     buf_pool)
3602
4463
{
3603
4464
        dulint*         index_ids;
3604
4465
        ulint*          counts;
3617
4478
        index_ids = mem_alloc(sizeof(dulint) * size);
3618
4479
        counts = mem_alloc(sizeof(ulint) * size);
3619
4480
 
3620
 
        buf_pool_mutex_enter();
 
4481
        buf_pool_mutex_enter(buf_pool);
 
4482
        buf_flush_list_mutex_enter(buf_pool);
3621
4483
 
3622
4484
        fprintf(stderr,
3623
4485
                "buf_pool size %lu\n"
3644
4506
                (ulong) buf_pool->stat.n_pages_created,
3645
4507
                (ulong) buf_pool->stat.n_pages_written);
3646
4508
 
 
4509
        buf_flush_list_mutex_exit(buf_pool);
 
4510
 
3647
4511
        /* Count the number of blocks belonging to each index in the buffer */
3648
4512
 
3649
4513
        n_found = 0;
3684
4548
                }
3685
4549
        }
3686
4550
 
3687
 
        buf_pool_mutex_exit();
 
4551
        buf_pool_mutex_exit(buf_pool);
3688
4552
 
3689
4553
        for (i = 0; i < n_found; i++) {
3690
4554
                index = dict_index_get_if_in_cache(index_ids[i]);
3705
4569
        mem_free(index_ids);
3706
4570
        mem_free(counts);
3707
4571
 
3708
 
        ut_a(buf_validate());
 
4572
        ut_a(buf_pool_validate_instance(buf_pool));
 
4573
}
 
4574
 
 
4575
/*********************************************************************//**
 
4576
Prints info of the buffer buf_pool data structure. */
 
4577
UNIV_INTERN
 
4578
void
 
4579
buf_print(void)
 
4580
/*===========*/
 
4581
{
 
4582
        ulint   i;
 
4583
 
 
4584
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4585
                buf_pool_t*     buf_pool;
 
4586
 
 
4587
                buf_pool = buf_pool_from_array(i);
 
4588
                buf_print_instance(buf_pool);
 
4589
        }
3709
4590
}
3710
4591
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
3711
4592
 
3715
4596
@return number of latched pages */
3716
4597
UNIV_INTERN
3717
4598
ulint
3718
 
buf_get_latched_pages_number(void)
3719
 
/*==============================*/
 
4599
buf_get_latched_pages_number_instance(
 
4600
/*==================================*/
 
4601
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3720
4602
{
3721
 
        buf_chunk_t*    chunk;
3722
4603
        buf_page_t*     b;
3723
4604
        ulint           i;
 
4605
        buf_chunk_t*    chunk;
3724
4606
        ulint           fixed_pages_number = 0;
3725
4607
 
3726
 
        buf_pool_mutex_enter();
 
4608
        buf_pool_mutex_enter(buf_pool);
3727
4609
 
3728
4610
        chunk = buf_pool->chunks;
3729
4611
 
3752
4634
                }
3753
4635
        }
3754
4636
 
3755
 
        mutex_enter(&buf_pool_zip_mutex);
 
4637
        mutex_enter(&buf_pool->zip_mutex);
3756
4638
 
3757
4639
        /* Traverse the lists of clean and dirty compressed-only blocks. */
3758
4640
 
3767
4649
                }
3768
4650
        }
3769
4651
 
 
4652
        buf_flush_list_mutex_enter(buf_pool);
3770
4653
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
3771
4654
             b = UT_LIST_GET_NEXT(list, b)) {
3772
4655
                ut_ad(b->in_flush_list);
3792
4675
                }
3793
4676
        }
3794
4677
 
3795
 
        mutex_exit(&buf_pool_zip_mutex);
3796
 
        buf_pool_mutex_exit();
 
4678
        buf_flush_list_mutex_exit(buf_pool);
 
4679
        mutex_exit(&buf_pool->zip_mutex);
 
4680
        buf_pool_mutex_exit(buf_pool);
3797
4681
 
3798
4682
        return(fixed_pages_number);
3799
4683
}
 
4684
 
 
4685
/*********************************************************************//**
 
4686
Returns the number of latched pages in all the buffer pools.
 
4687
@return number of latched pages */
 
4688
UNIV_INTERN
 
4689
ulint
 
4690
buf_get_latched_pages_number(void)
 
4691
/*==============================*/
 
4692
{
 
4693
        ulint   i;
 
4694
        ulint   total_latched_pages = 0;
 
4695
 
 
4696
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4697
                buf_pool_t*     buf_pool;
 
4698
 
 
4699
                buf_pool = buf_pool_from_array(i);
 
4700
 
 
4701
                total_latched_pages += buf_get_latched_pages_number_instance(
 
4702
                        buf_pool);
 
4703
        }
 
4704
 
 
4705
        return(total_latched_pages);
 
4706
}
 
4707
 
3800
4708
#endif /* UNIV_DEBUG */
3801
4709
 
3802
4710
/*********************************************************************//**
3807
4715
buf_get_n_pending_ios(void)
3808
4716
/*=======================*/
3809
4717
{
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]);
 
4718
        ulint   i;
 
4719
        ulint   pend_ios = 0;
 
4720
 
 
4721
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4722
                buf_pool_t*     buf_pool;
 
4723
 
 
4724
                buf_pool = buf_pool_from_array(i);
 
4725
 
 
4726
                pend_ios +=
 
4727
                        buf_pool->n_pend_reads
 
4728
                        + buf_pool->n_flush[BUF_FLUSH_LRU]
 
4729
                        + buf_pool->n_flush[BUF_FLUSH_LIST]
 
4730
                        + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
 
4731
        }
 
4732
 
 
4733
        return(pend_ios);
3814
4734
}
3815
4735
 
3816
4736
/*********************************************************************//**
3822
4742
buf_get_modified_ratio_pct(void)
3823
4743
/*============================*/
3824
4744
{
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
 
 
 
4745
        ulint           ratio;
 
4746
        ulint           lru_len = 0;
 
4747
        ulint           free_len = 0;
 
4748
        ulint           flush_list_len = 0;
 
4749
 
 
4750
        buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
 
4751
 
 
4752
        ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
 
4753
  
3833
4754
        /* 1 + is there to avoid division by zero */
3834
4755
 
3835
 
        buf_pool_mutex_exit();
3836
 
 
3837
4756
        return(ratio);
3838
4757
}
3839
4758
 
3840
4759
/*********************************************************************//**
3841
4760
Prints info of the buffer i/o. */
3842
 
UNIV_INTERN
 
4761
static
3843
4762
void
3844
 
buf_print_io(
3845
 
/*=========*/
3846
 
        FILE*   file)   /*!< in/out: buffer where to print */
 
4763
buf_print_io_instance(
 
4764
/*==================*/
 
4765
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
4766
        FILE*           file)           /*!< in/out: buffer where to print */
3847
4767
{
3848
4768
        time_t  current_time;
3849
4769
        double  time_elapsed;
3851
4771
 
3852
4772
        ut_ad(buf_pool);
3853
4773
 
3854
 
        buf_pool_mutex_enter();
 
4774
        buf_pool_mutex_enter(buf_pool);
 
4775
        buf_flush_list_mutex_enter(buf_pool);
3855
4776
 
3856
4777
        fprintf(file,
3857
4778
                "Buffer pool size   %lu\n"
3873
4794
                + buf_pool->init_flush[BUF_FLUSH_LIST],
3874
4795
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
3875
4796
 
 
4797
        buf_flush_list_mutex_exit(buf_pool);
 
4798
 
3876
4799
        current_time = time(NULL);
3877
4800
        time_elapsed = 0.001 + difftime(current_time,
3878
4801
                                        buf_pool->last_printout_time);
3903
4826
                 - buf_pool->old_stat.n_pages_written)
3904
4827
                / time_elapsed);
3905
4828
 
3906
 
        n_gets_diff = buf_pool->stat.n_page_gets - buf_pool->old_stat.n_page_gets;
 
4829
        n_gets_diff = buf_pool->stat.n_page_gets
 
4830
                    - buf_pool->old_stat.n_page_gets;
3907
4831
 
3908
4832
        if (n_gets_diff) {
3909
4833
                fprintf(file,
3947
4871
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
3948
4872
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
3949
4873
 
3950
 
        buf_refresh_io_stats();
3951
 
        buf_pool_mutex_exit();
 
4874
        buf_refresh_io_stats(buf_pool);
 
4875
        buf_pool_mutex_exit(buf_pool);
 
4876
}
 
4877
 
 
4878
/*********************************************************************//**
 
4879
Prints info of the buffer i/o. */
 
4880
UNIV_INTERN
 
4881
void
 
4882
buf_print_io(
 
4883
/*=========*/
 
4884
        FILE*   file)   /*!< in/out: buffer where to print */
 
4885
{
 
4886
        ulint   i;
 
4887
 
 
4888
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4889
                buf_pool_t*     buf_pool;
 
4890
 
 
4891
                buf_pool = buf_pool_from_array(i);
 
4892
                buf_print_io_instance(buf_pool, file);
 
4893
        }
3952
4894
}
3953
4895
 
3954
4896
/**********************************************************************//**
3955
4897
Refreshes the statistics used to print per-second averages. */
3956
4898
UNIV_INTERN
3957
4899
void
3958
 
buf_refresh_io_stats(void)
3959
 
/*======================*/
 
4900
buf_refresh_io_stats(
 
4901
/*=================*/
 
4902
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3960
4903
{
3961
 
        buf_pool->last_printout_time = time(NULL);
 
4904
        buf_pool->last_printout_time = ut_time();
3962
4905
        buf_pool->old_stat = buf_pool->stat;
3963
4906
}
3964
4907
 
3965
 
/*********************************************************************//**
3966
 
Asserts that all file pages in the buffer are in a replaceable state.
3967
 
@return TRUE */
 
4908
/**********************************************************************//**
 
4909
Refreshes the statistics used to print per-second averages. */
 
4910
UNIV_INTERN
 
4911
void
 
4912
buf_refresh_io_stats_all(void)
 
4913
/*==========================*/
 
4914
{
 
4915
        ulint           i;
 
4916
 
 
4917
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4918
                buf_pool_t*     buf_pool;
 
4919
 
 
4920
                buf_pool = buf_pool_from_array(i);
 
4921
 
 
4922
                buf_refresh_io_stats(buf_pool);
 
4923
        }
 
4924
}
 
4925
 
 
4926
/**********************************************************************//**
 
4927
Check if all pages in all buffer pools are in a replacable state.
 
4928
@return FALSE if not */
3968
4929
UNIV_INTERN
3969
4930
ibool
3970
4931
buf_all_freed(void)
3971
4932
/*===============*/
3972
4933
{
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;
 
4934
        ulint   i;
 
4935
 
 
4936
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4937
                buf_pool_t*     buf_pool;
 
4938
 
 
4939
                buf_pool = buf_pool_from_array(i);
 
4940
 
 
4941
                if (!buf_all_freed_instance(buf_pool)) {
 
4942
                        return(FALSE);
3992
4943
                }
3993
 
        }
3994
 
 
3995
 
        buf_pool_mutex_exit();
 
4944
        }
3996
4945
 
3997
4946
        return(TRUE);
3998
4947
}
3999
 
 
 
4948
  
4000
4949
/*********************************************************************//**
4001
4950
Checks that there currently are no pending i/o-operations for the buffer
4002
4951
pool.
4006
4955
buf_pool_check_no_pending_io(void)
4007
4956
/*==============================*/
4008
4957
{
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;
 
4958
        ulint           i;
 
4959
        ibool           ret = TRUE;
 
4960
 
 
4961
        buf_pool_mutex_enter_all();
 
4962
 
 
4963
        for (i = 0; i < srv_buf_pool_instances && ret; i++) {
 
4964
                const buf_pool_t*       buf_pool;
 
4965
 
 
4966
                buf_pool = buf_pool_from_array(i);
 
4967
 
 
4968
                if (buf_pool->n_pend_reads
 
4969
                    + buf_pool->n_flush[BUF_FLUSH_LRU]
 
4970
                    + buf_pool->n_flush[BUF_FLUSH_LIST]
 
4971
                    + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
 
4972
 
 
4973
                        ret = FALSE;
 
4974
                }
4019
4975
        }
4020
4976
 
4021
 
        buf_pool_mutex_exit();
 
4977
        buf_pool_mutex_exit_all();
4022
4978
 
4023
4979
        return(ret);
4024
4980
}
4025
4981
 
 
4982
#if 0
 
4983
Code currently not used
4026
4984
/*********************************************************************//**
4027
4985
Gets the current length of the free list of buffer blocks.
4028
4986
@return length of the free list */
4033
4991
{
4034
4992
        ulint   len;
4035
4993
 
4036
 
        buf_pool_mutex_enter();
 
4994
        buf_pool_mutex_enter(buf_pool);
4037
4995
 
4038
4996
        len = UT_LIST_GET_LEN(buf_pool->free);
4039
4997
 
4040
 
        buf_pool_mutex_exit();
 
4998
        buf_pool_mutex_exit(buf_pool);
4041
4999
 
4042
5000
        return(len);
4043
5001
}
 
5002
#endif
 
5003
 
4044
5004
#else /* !UNIV_HOTBACKUP */
4045
5005
/********************************************************************//**
4046
5006
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */