~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2010-10-27 21:00:49 UTC
  • mto: This revision was merged to the branch mainline in revision 1886.
  • Revision ID: brian@tangent.org-20101027210049-zfpgx2cfbrh8maq9
A couple of fixes to documentation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
7
7
Google, Inc. Those modifications are gratefully acknowledged and are described
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 normally be the case.
 
156
causing it to be replaced sooner than would noramlly 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
 
end of the LRU list, we make sure that most of the buf_pool stays
161
 
in the main memory, undisturbed.
 
160
of the LRU list, we make sure that most of the buf_pool stays in the
 
161
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 buf_pool->flush_list_mutex.
176
175
 
177
176
The chain of unmodified compressed blocks (buf_pool->zip_clean)
178
177
contains the control blocks (buf_page_t) of those compressed pages
243
242
#ifndef UNIV_HOTBACKUP
244
243
/** Value in microseconds */
245
244
static const int WAIT_FOR_READ  = 5000;
246
 
/** Number of attemtps made to read in a page in the buffer pool */
247
 
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
248
 
 
249
 
/** The buffer pools of the database */
250
 
UNIV_INTERN buf_pool_t* buf_pool_ptr;
 
245
 
 
246
/** The buffer buf_pool of the database */
 
247
UNIV_INTERN buf_pool_t* buf_pool = NULL;
 
248
 
 
249
/** mutex protecting the buffer pool struct and control blocks, except the
 
250
read-write lock in them */
 
251
UNIV_INTERN mutex_t             buf_pool_mutex;
 
252
/** mutex protecting the control blocks of compressed-only pages
 
253
(of type buf_page_t, not buf_block_t) */
 
254
UNIV_INTERN mutex_t             buf_pool_zip_mutex;
251
255
 
252
256
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
253
257
static ulint    buf_dbg_counter = 0; /*!< This is used to insert validation
254
 
                                        operations in execution in the
 
258
                                        operations in excution in the
255
259
                                        debug version */
 
260
/** Flag to forbid the release of the buffer pool mutex.
 
261
Protected by buf_pool_mutex. */
 
262
UNIV_INTERN ulint               buf_pool_mutex_exit_forbidden = 0;
256
263
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
257
264
#ifdef UNIV_DEBUG
258
265
/** If this is set TRUE, the program prints info whenever
260
267
UNIV_INTERN ibool               buf_debug_prints = FALSE;
261
268
#endif /* UNIV_DEBUG */
262
269
 
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
 
 
297
270
/** A chunk of buffers.  The buffer pool is allocated in chunks. */
298
271
struct buf_chunk_struct{
299
272
        ulint           mem_size;       /*!< allocated size of the chunk */
305
278
#endif /* !UNIV_HOTBACKUP */
306
279
 
307
280
/********************************************************************//**
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
 
/********************************************************************//**
442
281
Calculates a page checksum which is stored to the page when it is written
443
282
to a file. Note that we must be careful to calculate the same value on
444
283
32-bit and 64-bit architectures.
522
361
                ib_uint64_t     current_lsn;
523
362
 
524
363
                if (log_peek_lsn(&current_lsn)
525
 
                    && UNIV_UNLIKELY
526
 
                    (current_lsn
527
 
                     < mach_read_from_8(read_buf + FIL_PAGE_LSN))) {
 
364
                    && current_lsn < mach_read_ull(read_buf + FIL_PAGE_LSN)) {
528
365
                        ut_print_timestamp(stderr);
529
366
 
530
367
                        fprintf(stderr,
540
377
                                "InnoDB: for more information.\n",
541
378
                                (ulong) mach_read_from_4(read_buf
542
379
                                                         + FIL_PAGE_OFFSET),
543
 
                                mach_read_from_8(read_buf + FIL_PAGE_LSN),
 
380
                                mach_read_ull(read_buf + FIL_PAGE_LSN),
544
381
                                current_lsn);
545
382
                }
546
383
        }
737
574
#endif /* !UNIV_HOTBACKUP */
738
575
 
739
576
        switch (fil_page_get_type(read_buf)) {
740
 
                index_id_t      index_id;
741
577
        case FIL_PAGE_INDEX:
742
 
                index_id = btr_page_get_index_id(read_buf);
743
578
                fprintf(stderr,
744
579
                        "InnoDB: Page may be an index page where"
745
 
                        " index id is %llu\n",
746
 
                        (ullint) index_id);
 
580
                        " index id is %lu %lu\n",
 
581
                        (ulong) ut_dulint_get_high(
 
582
                                btr_page_get_index_id(read_buf)),
 
583
                        (ulong) ut_dulint_get_low(
 
584
                                btr_page_get_index_id(read_buf)));
747
585
#ifndef UNIV_HOTBACKUP
748
 
                index = dict_index_find_on_id_low(index_id);
 
586
                index = dict_index_find_on_id_low(
 
587
                        btr_page_get_index_id(read_buf));
749
588
                if (index) {
750
589
                        fputs("InnoDB: (", stderr);
751
590
                        dict_index_name_print(stderr, NULL, index);
797
636
}
798
637
 
799
638
#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
 
 
847
639
/********************************************************************//**
848
640
Initializes a buffer control block when the buf_pool is created. */
849
641
static
850
642
void
851
643
buf_block_init(
852
644
/*===========*/
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 */
 
645
        buf_block_t*    block,  /*!< in: pointer to control block */
 
646
        byte*           frame)  /*!< in: pointer to buffer frame */
856
647
{
857
648
        UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
858
649
 
859
650
        block->frame = frame;
860
651
 
861
 
        block->page.buf_pool_index = buf_pool_index(buf_pool);
862
652
        block->page.state = BUF_BLOCK_NOT_USED;
863
653
        block->page.buf_fix_count = 0;
864
654
        block->page.io_fix = BUF_IO_NONE;
872
662
        block->check_index_page_at_flush = FALSE;
873
663
        block->index = NULL;
874
664
 
875
 
        block->is_hashed = FALSE;
876
 
 
877
665
#ifdef UNIV_DEBUG
878
666
        block->page.in_page_hash = FALSE;
879
667
        block->page.in_zip_hash = FALSE;
887
675
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
888
676
        page_zip_des_init(&block->page.zip);
889
677
 
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
 
 
 
678
        mutex_create(&block->mutex, SYNC_BUF_BLOCK);
 
679
 
 
680
        rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
904
681
        ut_ad(rw_lock_validate(&(block->lock)));
905
682
 
906
683
#ifdef UNIV_SYNC_DEBUG
907
 
        rw_lock_create(buf_block_debug_latch_key,
908
 
                       &block->debug_latch, SYNC_NO_ORDER_CHECK);
 
684
        rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
909
685
#endif /* UNIV_SYNC_DEBUG */
910
686
}
911
687
 
916
692
buf_chunk_t*
917
693
buf_chunk_init(
918
694
/*===========*/
919
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
920
695
        buf_chunk_t*    chunk,          /*!< out: chunk of buffers */
921
696
        ulint           mem_size)       /*!< in: requested size in bytes */
922
697
{
941
716
 
942
717
        /* Allocate the block descriptors from
943
718
        the start of the memory block. */
944
 
        chunk->blocks = static_cast<buf_block_struct *>(chunk->mem);
 
719
        chunk->blocks = chunk->mem;
945
720
 
946
721
        /* Align a pointer to the first frame.  Note that when
947
722
        os_large_page_size is smaller than UNIV_PAGE_SIZE,
948
723
        we may allocate one fewer block than requested.  When
949
724
        it is bigger, we may allocate more blocks than requested. */
950
725
 
951
 
        frame = static_cast<unsigned char *>(ut_align(chunk->mem, UNIV_PAGE_SIZE));
 
726
        frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
952
727
        chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
953
728
                - (frame != chunk->mem);
954
729
 
972
747
 
973
748
        for (i = chunk->size; i--; ) {
974
749
 
975
 
                buf_block_init(buf_pool, block, frame);
 
750
                buf_block_init(block, frame);
976
751
 
977
752
#ifdef HAVE_VALGRIND
978
753
                /* Wipe contents of frame to eliminate a Purify warning */
980
755
#endif
981
756
                /* Add the block to the free list */
982
757
                UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
983
 
 
984
758
                ut_d(block->page.in_free_list = TRUE);
985
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
986
759
 
987
760
                block++;
988
761
                frame += UNIV_PAGE_SIZE;
989
762
        }
990
763
 
991
 
#ifdef PFS_GROUP_BUFFER_SYNC
992
 
        pfs_register_buffer_block(chunk);
993
 
#endif
994
764
        return(chunk);
995
765
}
996
766
 
1009
779
        buf_block_t*    block;
1010
780
        ulint           i;
1011
781
 
 
782
        ut_ad(buf_pool);
 
783
        ut_ad(buf_pool_mutex_own());
 
784
 
1012
785
        block = chunk->blocks;
1013
786
 
1014
787
        for (i = chunk->size; i--; block++) {
1029
802
buf_block_t*
1030
803
buf_pool_contains_zip(
1031
804
/*==================*/
1032
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1033
 
        const void*     data)           /*!< in: pointer to compressed page */
 
805
        const void*     data)   /*!< in: pointer to compressed page */
1034
806
{
1035
807
        ulint           n;
1036
808
        buf_chunk_t*    chunk = buf_pool->chunks;
1037
809
 
1038
 
        ut_ad(buf_pool);
1039
 
        ut_ad(buf_pool_mutex_own(buf_pool));
1040
810
        for (n = buf_pool->n_chunks; n--; chunk++) {
1041
 
 
1042
811
                buf_block_t* block = buf_chunk_contains_zip(chunk, data);
1043
812
 
1044
813
                if (block) {
1062
831
        buf_block_t*    block;
1063
832
        ulint           i;
1064
833
 
 
834
        ut_ad(buf_pool);
 
835
        ut_ad(buf_pool_mutex_own());
 
836
 
1065
837
        block = chunk->blocks;
1066
838
 
1067
839
        for (i = chunk->size; i--; block++) {
1111
883
        const buf_block_t*      block;
1112
884
        ulint                   i;
1113
885
 
 
886
        ut_ad(buf_pool);
 
887
        ut_ad(buf_pool_mutex_own());
 
888
 
1114
889
        block = chunk->blocks;
1115
890
 
1116
891
        for (i = chunk->size; i--; block++) {
1130
905
void
1131
906
buf_chunk_free(
1132
907
/*===========*/
1133
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1134
908
        buf_chunk_t*    chunk)          /*!< out: chunk of buffers */
1135
909
{
1136
910
        buf_block_t*            block;
1137
911
        const buf_block_t*      block_end;
1138
912
 
1139
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
913
        ut_ad(buf_pool_mutex_own());
1140
914
 
1141
915
        block_end = chunk->blocks + chunk->size;
1142
916
 
1164
938
}
1165
939
 
1166
940
/********************************************************************//**
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
 
{
 
941
Creates the buffer pool.
 
942
@return own: buf_pool object, NULL if not enough memory or error */
 
943
UNIV_INTERN
 
944
buf_pool_t*
 
945
buf_pool_init(void)
 
946
/*===============*/
 
947
{
 
948
        buf_chunk_t*    chunk;
1202
949
        ulint           i;
1203
 
        buf_chunk_t*    chunk;
 
950
 
 
951
        buf_pool = mem_zalloc(sizeof(buf_pool_t));
1204
952
 
1205
953
        /* 1. Initialize general fields
1206
954
        ------------------------------- */
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
 
                void *chunk_ptr= mem_zalloc((sizeof *chunk));
1217
 
                buf_pool->chunks = chunk = static_cast<buf_chunk_t *>(chunk_ptr);
1218
 
 
1219
 
                UT_LIST_INIT(buf_pool->free);
1220
 
 
1221
 
                if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
1222
 
                        mem_free(chunk);
1223
 
                        mem_free(buf_pool);
1224
 
 
1225
 
                        buf_pool_mutex_exit(buf_pool);
1226
 
 
1227
 
                        return(DB_ERROR);
1228
 
                }
1229
 
 
1230
 
                buf_pool->instance_no = instance_no;
1231
 
                buf_pool->old_pool_size = buf_pool_size;
1232
 
                buf_pool->curr_size = chunk->size;
1233
 
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1234
 
 
1235
 
                buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
1236
 
                buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
1237
 
                
1238
 
                buf_pool->last_printout_time = ut_time();
 
955
        mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
 
956
        mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
 
957
 
 
958
        buf_pool_mutex_enter();
 
959
 
 
960
        buf_pool->n_chunks = 1;
 
961
        buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
 
962
 
 
963
        UT_LIST_INIT(buf_pool->free);
 
964
 
 
965
        if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
 
966
                mem_free(chunk);
 
967
                mem_free(buf_pool);
 
968
                buf_pool = NULL;
 
969
                return(NULL);
1239
970
        }
 
971
 
 
972
        srv_buf_pool_old_size = srv_buf_pool_size;
 
973
        buf_pool->curr_size = chunk->size;
 
974
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
975
 
 
976
        buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
 
977
        buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
 
978
 
 
979
        buf_pool->last_printout_time = time(NULL);
 
980
 
1240
981
        /* 2. Initialize flushing fields
1241
982
        -------------------------------- */
1242
983
 
1243
 
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1244
 
                     SYNC_BUF_FLUSH_LIST);
1245
 
 
1246
984
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
1247
985
                buf_pool->no_flush[i] = os_event_create(NULL);
1248
986
        }
1249
987
 
1250
988
        /* 3. Initialize LRU fields
1251
989
        --------------------------- */
1252
 
 
1253
 
        /* All fields are initialized by mem_zalloc(). */
1254
 
 
1255
 
        buf_pool_mutex_exit(buf_pool);
1256
 
 
1257
 
        return(DB_SUCCESS);
 
990
        /* All fields are initialized by mem_zalloc(). */
 
991
 
 
992
        buf_pool_mutex_exit();
 
993
 
 
994
        btr_search_sys_create(buf_pool->curr_size
 
995
                              * UNIV_PAGE_SIZE / sizeof(void*) / 64);
 
996
 
 
997
        /* 4. Initialize the buddy allocator fields */
 
998
        /* All fields are initialized by mem_zalloc(). */
 
999
 
 
1000
        return(buf_pool);
1258
1001
}
1259
1002
 
1260
1003
/********************************************************************//**
1261
 
free one buffer pool instance */
1262
 
static
 
1004
Frees the buffer pool at shutdown.  This must not be invoked before
 
1005
freeing all mutexes. */
 
1006
UNIV_INTERN
1263
1007
void
1264
 
buf_pool_free_instance(
1265
 
/*===================*/
1266
 
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
1267
 
                                        to free */
 
1008
buf_pool_free(void)
 
1009
/*===============*/
1268
1010
{
1269
1011
        buf_chunk_t*    chunk;
1270
1012
        buf_chunk_t*    chunks;
1281
1023
        mem_free(buf_pool->chunks);
1282
1024
        hash_table_free(buf_pool->page_hash);
1283
1025
        hash_table_free(buf_pool->zip_hash);
1284
 
}
1285
 
 
1286
 
/********************************************************************//**
1287
 
Creates the buffer pool.
1288
 
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
1289
 
UNIV_INTERN
1290
 
ulint
1291
 
buf_pool_init(
1292
 
/*==========*/
1293
 
        ulint   total_size,     /*!< in: size of the total pool in bytes */
1294
 
        ulint   n_instances)    /*!< in: number of instances */
1295
 
{
1296
 
        ulint           i;
1297
 
        const ulint     size    = total_size / n_instances;
1298
 
 
1299
 
        ut_ad(n_instances > 0);
1300
 
        ut_ad(n_instances <= MAX_BUFFER_POOLS);
1301
 
        ut_ad(n_instances == srv_buf_pool_instances);
1302
 
 
1303
 
        /* We create an extra buffer pool instance, this instance is used
1304
 
        for flushing the flush lists, to keep track of n_flush for all
1305
 
        the buffer pools and also used as a waiting object during flushing. */
1306
 
        void *buf_pool_void_ptr= mem_zalloc(n_instances * sizeof *buf_pool_ptr);
1307
 
        buf_pool_ptr = static_cast<buf_pool_struct *>(buf_pool_void_ptr);
1308
 
 
1309
 
        for (i = 0; i < n_instances; i++) {
1310
 
                buf_pool_t*     ptr     = &buf_pool_ptr[i];
1311
 
 
1312
 
                if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
1313
 
 
1314
 
                        /* Free all the instances created so far. */
1315
 
                        buf_pool_free(i);
1316
 
 
1317
 
                        return(DB_ERROR);
1318
 
                }
1319
 
        }
1320
 
 
1321
 
        buf_pool_set_sizes();
1322
 
        buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
1323
 
 
1324
 
        btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
1325
 
 
1326
 
        return(DB_SUCCESS);
1327
 
}
1328
 
 
1329
 
/********************************************************************//**
1330
 
Frees the buffer pool at shutdown.  This must not be invoked before
1331
 
freeing all mutexes. */
1332
 
UNIV_INTERN
1333
 
void
1334
 
buf_pool_free(
1335
 
/*==========*/
1336
 
        ulint   n_instances)    /*!< in: numbere of instances to free */
1337
 
{
1338
 
        ulint   i;
1339
 
 
1340
 
        for (i = 0; i < n_instances; i++) {
1341
 
                buf_pool_free_instance(buf_pool_from_array(i));
1342
 
        }
1343
 
 
1344
 
        mem_free(buf_pool_ptr);
1345
 
        buf_pool_ptr = NULL;
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
 
 
 
1026
        mem_free(buf_pool);
 
1027
        buf_pool = NULL;
 
1028
}
 
1029
 
1420
1030
/********************************************************************//**
1421
1031
Drops the adaptive hash index.  To prevent a livelock, this function
1422
1032
is only to be called while holding btr_search_latch and while
1434
1044
        ut_ad(!btr_search_enabled);
1435
1045
 
1436
1046
        do {
1437
 
                ulint   i;
 
1047
                buf_chunk_t*    chunks  = buf_pool->chunks;
 
1048
                buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
1438
1049
 
1439
1050
                released_search_latch = FALSE;
1440
1051
 
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);
 
1052
                while (--chunk >= chunks) {
 
1053
                        buf_block_t*    block   = chunk->blocks;
 
1054
                        ulint           i       = chunk->size;
 
1055
 
 
1056
                        for (; i--; block++) {
 
1057
                                /* block->is_hashed cannot be modified
 
1058
                                when we have an x-latch on btr_search_latch;
 
1059
                                see the comment in buf0buf.h */
 
1060
 
 
1061
                                if (!block->is_hashed) {
 
1062
                                        continue;
 
1063
                                }
 
1064
 
 
1065
                                /* To follow the latching order, we
 
1066
                                have to release btr_search_latch
 
1067
                                before acquiring block->latch. */
 
1068
                                rw_lock_x_unlock(&btr_search_latch);
 
1069
                                /* When we release the search latch,
 
1070
                                we must rescan all blocks, because
 
1071
                                some may become hashed again. */
 
1072
                                released_search_latch = TRUE;
 
1073
 
 
1074
                                rw_lock_x_lock(&block->lock);
 
1075
 
 
1076
                                /* This should be guaranteed by the
 
1077
                                callers, which will be holding
 
1078
                                btr_search_enabled_mutex. */
 
1079
                                ut_ad(!btr_search_enabled);
 
1080
 
 
1081
                                /* Because we did not buffer-fix the
 
1082
                                block by calling buf_block_get_gen(),
 
1083
                                it is possible that the block has been
 
1084
                                allocated for some other use after
 
1085
                                btr_search_latch was released above.
 
1086
                                We do not care which file page the
 
1087
                                block is mapped to.  All we want to do
 
1088
                                is to drop any hash entries referring
 
1089
                                to the page. */
 
1090
 
 
1091
                                /* It is possible that
 
1092
                                block->page.state != BUF_FILE_PAGE.
 
1093
                                Even that does not matter, because
 
1094
                                btr_search_drop_page_hash_index() will
 
1095
                                check block->is_hashed before doing
 
1096
                                anything.  block->is_hashed can only
 
1097
                                be set on uncompressed file pages. */
 
1098
 
 
1099
                                btr_search_drop_page_hash_index(block);
 
1100
 
 
1101
                                rw_lock_x_unlock(&block->lock);
 
1102
 
 
1103
                                rw_lock_x_lock(&btr_search_latch);
 
1104
 
 
1105
                                ut_ad(!btr_search_enabled);
 
1106
                        }
1448
1107
                }
1449
 
 
1450
1108
        } while (released_search_latch);
1451
1109
}
1452
1110
 
1465
1123
{
1466
1124
        buf_page_t*     b;
1467
1125
        ulint           fold;
1468
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1469
1126
 
1470
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1127
        ut_ad(buf_pool_mutex_own());
1471
1128
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1472
1129
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1473
1130
        ut_a(bpage->buf_fix_count == 0);
1474
1131
        ut_ad(bpage->in_LRU_list);
1475
1132
        ut_ad(!bpage->in_zip_hash);
1476
1133
        ut_ad(bpage->in_page_hash);
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));
 
1134
        ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
1480
1135
#ifdef UNIV_DEBUG
1481
1136
        switch (buf_page_get_state(bpage)) {
1482
1137
        case BUF_BLOCK_ZIP_FREE:
1532
1187
 
1533
1188
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
1534
1189
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
 
1190
 
 
1191
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
1535
1192
}
1536
1193
 
1537
1194
/********************************************************************//**
1538
 
Shrinks a buffer pool instance. */
 
1195
Shrinks the buffer pool. */
1539
1196
static
1540
1197
void
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 */
 
1198
buf_pool_shrink(
 
1199
/*============*/
 
1200
        ulint   chunk_size)     /*!< in: number of pages to remove */
1545
1201
{
1546
1202
        buf_chunk_t*    chunks;
1547
1203
        buf_chunk_t*    chunk;
1550
1206
        buf_chunk_t*    max_chunk;
1551
1207
        buf_chunk_t*    max_free_chunk;
1552
1208
 
1553
 
        ut_ad(!buf_pool_mutex_own(buf_pool));
 
1209
        ut_ad(!buf_pool_mutex_own());
1554
1210
 
1555
1211
try_again:
1556
1212
        btr_search_disable(); /* Empty the adaptive hash index again */
1557
 
        buf_pool_mutex_enter(buf_pool);
 
1213
        buf_pool_mutex_enter();
1558
1214
 
1559
1215
shrink_again:
1560
1216
        if (buf_pool->n_chunks <= 1) {
1617
1273
 
1618
1274
                        mutex_enter(&block->mutex);
1619
1275
                        /* The following calls will temporarily
1620
 
                        release block->mutex and buf_pool->mutex.
 
1276
                        release block->mutex and buf_pool_mutex.
1621
1277
                        Therefore, we have to always retry,
1622
1278
                        even if !dirty && !nonfree. */
1623
1279
 
1633
1289
                        mutex_exit(&block->mutex);
1634
1290
                }
1635
1291
 
1636
 
                buf_pool_mutex_exit(buf_pool);
 
1292
                buf_pool_mutex_exit();
1637
1293
 
1638
1294
                /* Request for a flush of the chunk if it helps.
1639
1295
                Do not flush if there are non-free blocks, since
1642
1298
                        /* Avoid busy-waiting. */
1643
1299
                        os_thread_sleep(100000);
1644
1300
                } else if (dirty
1645
 
                           && buf_flush_LRU(buf_pool, dirty)
1646
 
                              == ULINT_UNDEFINED) {
 
1301
                           && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
 
1302
                           == ULINT_UNDEFINED) {
1647
1303
 
1648
 
                        buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
 
1304
                        buf_flush_wait_batch_end(BUF_FLUSH_LRU);
1649
1305
                }
1650
1306
 
1651
1307
                goto try_again;
1654
1310
        max_size = max_free_size;
1655
1311
        max_chunk = max_free_chunk;
1656
1312
 
1657
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1313
        srv_buf_pool_old_size = srv_buf_pool_size;
1658
1314
 
1659
1315
        /* Rewrite buf_pool->chunks.  Copy everything but max_chunk. */
1660
 
        chunks = static_cast<buf_chunk_t *>(mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks));
 
1316
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
1661
1317
        memcpy(chunks, buf_pool->chunks,
1662
1318
               (max_chunk - buf_pool->chunks) * sizeof *chunks);
1663
1319
        memcpy(chunks + (max_chunk - buf_pool->chunks),
1666
1322
               - (max_chunk + 1));
1667
1323
        ut_a(buf_pool->curr_size > max_chunk->size);
1668
1324
        buf_pool->curr_size -= max_chunk->size;
1669
 
        buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1325
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1670
1326
        chunk_size -= max_chunk->size;
1671
 
        buf_chunk_free(buf_pool, max_chunk);
 
1327
        buf_chunk_free(max_chunk);
1672
1328
        mem_free(buf_pool->chunks);
1673
1329
        buf_pool->chunks = chunks;
1674
1330
        buf_pool->n_chunks--;
1678
1334
 
1679
1335
                goto shrink_again;
1680
1336
        }
1681
 
        goto func_exit;
1682
1337
 
1683
1338
func_done:
1684
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1339
        srv_buf_pool_old_size = srv_buf_pool_size;
1685
1340
func_exit:
1686
 
        buf_pool_mutex_exit(buf_pool);
 
1341
        buf_pool_mutex_exit();
1687
1342
        btr_search_enable();
1688
1343
}
1689
1344
 
1690
1345
/********************************************************************//**
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 */
 
1346
Rebuild buf_pool->page_hash. */
 
1347
static
 
1348
void
 
1349
buf_pool_page_hash_rebuild(void)
 
1350
/*============================*/
1719
1351
{
1720
1352
        ulint           i;
1721
 
        buf_page_t*     b;
1722
 
        buf_chunk_t*    chunk;
1723
1353
        ulint           n_chunks;
 
1354
        buf_chunk_t*    chunk;
 
1355
        hash_table_t*   page_hash;
1724
1356
        hash_table_t*   zip_hash;
1725
 
        hash_table_t*   page_hash;
 
1357
        buf_page_t*     b;
1726
1358
 
1727
 
        buf_pool_mutex_enter(buf_pool);
 
1359
        buf_pool_mutex_enter();
1728
1360
 
1729
1361
        /* Free, create, and populate the hash table. */
1730
1362
        hash_table_free(buf_pool->page_hash);
1777
1409
                            buf_page_address_fold(b->space, b->offset), b);
1778
1410
        }
1779
1411
 
1780
 
        buf_flush_list_mutex_enter(buf_pool);
1781
1412
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1782
1413
             b = UT_LIST_GET_NEXT(list, b)) {
1783
1414
                ut_ad(b->in_flush_list);
1805
1436
                }
1806
1437
        }
1807
1438
 
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 = static_cast<buf_chunk_t *>(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();
 
1439
        buf_pool_mutex_exit();
1982
1440
}
1983
1441
 
1984
1442
/********************************************************************//**
1988
1446
buf_pool_resize(void)
1989
1447
/*=================*/
1990
1448
{
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
 
 
 
1449
        buf_pool_mutex_enter();
 
1450
 
 
1451
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
 
1452
 
 
1453
                buf_pool_mutex_exit();
2029
1454
                return;
2030
1455
        }
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);
 
1456
 
 
1457
        if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
 
1458
 
 
1459
                buf_pool_mutex_exit();
 
1460
 
 
1461
                /* Disable adaptive hash indexes and empty the index
 
1462
                in order to free up memory in the buffer pool chunks. */
 
1463
                buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
 
1464
                                / UNIV_PAGE_SIZE);
 
1465
        } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
 
1466
 
 
1467
                /* Enlarge the buffer pool by at least one megabyte */
 
1468
 
 
1469
                ulint           mem_size
 
1470
                        = srv_buf_pool_size - srv_buf_pool_curr_size;
 
1471
                buf_chunk_t*    chunks;
 
1472
                buf_chunk_t*    chunk;
 
1473
 
 
1474
                chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
 
1475
 
 
1476
                memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
 
1477
                       * sizeof *chunks);
 
1478
 
 
1479
                chunk = &chunks[buf_pool->n_chunks];
 
1480
 
 
1481
                if (!buf_chunk_init(chunk, mem_size)) {
 
1482
                        mem_free(chunks);
 
1483
                } else {
 
1484
                        buf_pool->curr_size += chunk->size;
 
1485
                        srv_buf_pool_curr_size = buf_pool->curr_size
 
1486
                                * UNIV_PAGE_SIZE;
 
1487
                        mem_free(buf_pool->chunks);
 
1488
                        buf_pool->chunks = chunks;
 
1489
                        buf_pool->n_chunks++;
2089
1490
                }
 
1491
 
 
1492
                srv_buf_pool_old_size = srv_buf_pool_size;
 
1493
                buf_pool_mutex_exit();
2090
1494
        }
2091
1495
 
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);
 
1496
        buf_pool_page_hash_rebuild();
2122
1497
}
2123
1498
 
2124
1499
/********************************************************************//**
2131
1506
/*================*/
2132
1507
        buf_page_t*     bpage)  /*!< in: buffer block of a file page */
2133
1508
{
2134
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2135
 
 
2136
 
        buf_pool_mutex_enter(buf_pool);
 
1509
        buf_pool_mutex_enter();
2137
1510
 
2138
1511
        ut_a(buf_page_in_file(bpage));
2139
1512
 
2140
1513
        buf_LRU_make_block_young(bpage);
2141
1514
 
2142
 
        buf_pool_mutex_exit(buf_pool);
 
1515
        buf_pool_mutex_exit();
2143
1516
}
2144
1517
 
2145
1518
/********************************************************************//**
2157
1530
                                        read under mutex protection,
2158
1531
                                        or 0 if unknown */
2159
1532
{
2160
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2161
 
 
2162
 
        ut_ad(!buf_pool_mutex_own(buf_pool));
 
1533
        ut_ad(!buf_pool_mutex_own());
2163
1534
        ut_a(buf_page_in_file(bpage));
2164
1535
 
2165
1536
        if (buf_page_peek_if_too_old(bpage)) {
2166
 
                buf_pool_mutex_enter(buf_pool);
 
1537
                buf_pool_mutex_enter();
2167
1538
                buf_LRU_make_block_young(bpage);
2168
 
                buf_pool_mutex_exit(buf_pool);
 
1539
                buf_pool_mutex_exit();
2169
1540
        } else if (!access_time) {
2170
1541
                ulint   time_ms = ut_time_ms();
2171
 
                buf_pool_mutex_enter(buf_pool);
 
1542
                buf_pool_mutex_enter();
2172
1543
                buf_page_set_accessed(bpage, time_ms);
2173
 
                buf_pool_mutex_exit(buf_pool);
 
1544
                buf_pool_mutex_exit();
2174
1545
        }
2175
1546
}
2176
1547
 
2185
1556
        ulint   offset) /*!< in: page number */
2186
1557
{
2187
1558
        buf_block_t*    block;
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);
 
1559
 
 
1560
        buf_pool_mutex_enter();
 
1561
 
 
1562
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2193
1563
 
2194
1564
        if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
2195
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2196
1565
                block->check_index_page_at_flush = FALSE;
2197
1566
        }
2198
1567
 
2199
 
        buf_pool_mutex_exit(buf_pool);
 
1568
        buf_pool_mutex_exit();
2200
1569
}
2201
1570
 
2202
1571
/********************************************************************//**
2213
1582
{
2214
1583
        buf_block_t*    block;
2215
1584
        ibool           is_hashed;
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);
 
1585
 
 
1586
        buf_pool_mutex_enter();
 
1587
 
 
1588
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2221
1589
 
2222
1590
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2223
1591
                is_hashed = FALSE;
2224
1592
        } else {
2225
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2226
1593
                is_hashed = block->is_hashed;
2227
1594
        }
2228
1595
 
2229
 
        buf_pool_mutex_exit(buf_pool);
 
1596
        buf_pool_mutex_exit();
2230
1597
 
2231
1598
        return(is_hashed);
2232
1599
}
2246
1613
        ulint   offset) /*!< in: page number */
2247
1614
{
2248
1615
        buf_page_t*     bpage;
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);
 
1616
 
 
1617
        buf_pool_mutex_enter();
 
1618
 
 
1619
        bpage = buf_page_hash_get(space, offset);
2254
1620
 
2255
1621
        if (bpage) {
2256
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2257
1622
                bpage->file_page_was_freed = TRUE;
2258
1623
        }
2259
1624
 
2260
 
        buf_pool_mutex_exit(buf_pool);
 
1625
        buf_pool_mutex_exit();
2261
1626
 
2262
1627
        return(bpage);
2263
1628
}
2276
1641
        ulint   offset) /*!< in: page number */
2277
1642
{
2278
1643
        buf_page_t*     bpage;
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);
 
1644
 
 
1645
        buf_pool_mutex_enter();
 
1646
 
 
1647
        bpage = buf_page_hash_get(space, offset);
2284
1648
 
2285
1649
        if (bpage) {
2286
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2287
1650
                bpage->file_page_was_freed = FALSE;
2288
1651
        }
2289
1652
 
2290
 
        buf_pool_mutex_exit(buf_pool);
 
1653
        buf_pool_mutex_exit();
2291
1654
 
2292
1655
        return(bpage);
2293
1656
}
2314
1677
        mutex_t*        block_mutex;
2315
1678
        ibool           must_read;
2316
1679
        unsigned        access_time;
2317
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2318
1680
 
2319
1681
#ifndef UNIV_LOG_DEBUG
2320
1682
        ut_ad(!ibuf_inside());
2322
1684
        buf_pool->stat.n_page_gets++;
2323
1685
 
2324
1686
        for (;;) {
2325
 
                buf_pool_mutex_enter(buf_pool);
 
1687
                buf_pool_mutex_enter();
2326
1688
lookup:
2327
 
                bpage = buf_page_hash_get(buf_pool, space, offset);
 
1689
                bpage = buf_page_hash_get(space, offset);
2328
1690
                if (bpage) {
2329
 
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2330
1691
                        break;
2331
1692
                }
2332
1693
 
2333
1694
                /* Page not in buf_pool: needs to be read from file */
2334
1695
 
2335
 
                buf_pool_mutex_exit(buf_pool);
 
1696
                buf_pool_mutex_exit();
2336
1697
 
2337
1698
                buf_read_page(space, zip_size, offset);
2338
1699
 
2344
1705
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
2345
1706
                /* There is no compressed page. */
2346
1707
err_exit:
2347
 
                buf_pool_mutex_exit(buf_pool);
 
1708
                buf_pool_mutex_exit();
2348
1709
                return(NULL);
2349
1710
        }
2350
1711
 
2351
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2352
 
 
2353
1712
        switch (buf_page_get_state(bpage)) {
2354
1713
        case BUF_BLOCK_NOT_USED:
2355
1714
        case BUF_BLOCK_READY_FOR_USE:
2359
1718
                break;
2360
1719
        case BUF_BLOCK_ZIP_PAGE:
2361
1720
        case BUF_BLOCK_ZIP_DIRTY:
2362
 
                block_mutex = &buf_pool->zip_mutex;
 
1721
                block_mutex = &buf_pool_zip_mutex;
2363
1722
                mutex_enter(block_mutex);
2364
1723
                bpage->buf_fix_count++;
2365
1724
                goto got_block;
2387
1746
        must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
2388
1747
        access_time = buf_page_is_accessed(bpage);
2389
1748
 
2390
 
        buf_pool_mutex_exit(buf_pool);
 
1749
        buf_pool_mutex_exit();
2391
1750
 
2392
1751
        mutex_exit(block_mutex);
2393
1752
 
2459
1818
        buf_block_t*    block,  /*!< in/out: block */
2460
1819
        ibool           check)  /*!< in: TRUE=verify the page checksum */
2461
1820
{
2462
 
        const byte*     frame           = block->page.zip.data;
2463
 
        ulint           stamp_checksum  = mach_read_from_4(
2464
 
                frame + FIL_PAGE_SPACE_OR_CHKSUM);
 
1821
        const byte* frame = block->page.zip.data;
2465
1822
 
2466
1823
        ut_ad(buf_block_get_zip_size(block));
2467
1824
        ut_a(buf_block_get_space(block) != 0);
2468
1825
 
2469
 
        if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
 
1826
        if (UNIV_LIKELY(check)) {
 
1827
                ulint   stamp_checksum  = mach_read_from_4(
 
1828
                        frame + FIL_PAGE_SPACE_OR_CHKSUM);
2470
1829
                ulint   calc_checksum   = page_zip_calc_checksum(
2471
1830
                        frame, page_zip_get_size(&block->page.zip));
2472
1831
 
2517
1876
 
2518
1877
#ifndef UNIV_HOTBACKUP
2519
1878
/*******************************************************************//**
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
 
1879
Gets the block to whose frame the pointer is pointing to.
 
1880
@return pointer to block, never NULL */
 
1881
UNIV_INTERN
2524
1882
buf_block_t*
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 */
 
1883
buf_block_align(
 
1884
/*============*/
 
1885
        const byte*     ptr)    /*!< in: pointer to a frame */
2530
1886
{
2531
1887
        buf_chunk_t*    chunk;
2532
1888
        ulint           i;
2552
1908
                        ut_ad(block->frame == page_align(ptr));
2553
1909
#ifdef UNIV_DEBUG
2554
1910
                        /* A thread that updates these fields must
2555
 
                        hold buf_pool->mutex and block->mutex.  Acquire
 
1911
                        hold buf_pool_mutex and block->mutex.  Acquire
2556
1912
                        only the latter. */
2557
1913
                        mutex_enter(&block->mutex);
2558
1914
 
2601
1957
                }
2602
1958
        }
2603
1959
 
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
 
 
2628
1960
        /* The block should always be found. */
2629
1961
        ut_error;
2630
1962
        return(NULL);
2632
1964
 
2633
1965
/********************************************************************//**
2634
1966
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
2635
 
the buf_block_t itself or a member of it. This functions checks one of
2636
 
the buffer pool instances.
 
1967
the buf_block_t itself or a member of it
2637
1968
@return TRUE if ptr belongs to a buf_block_t struct */
2638
 
static
 
1969
UNIV_INTERN
2639
1970
ibool
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 */
 
1971
buf_pointer_is_block_field(
 
1972
/*=======================*/
 
1973
        const void*             ptr)    /*!< in: pointer not
 
1974
                                        dereferenced */
2644
1975
{
2645
1976
        const buf_chunk_t*              chunk   = buf_pool->chunks;
2646
1977
        const buf_chunk_t* const        echunk  = chunk + buf_pool->n_chunks;
2661
1992
}
2662
1993
 
2663
1994
/********************************************************************//**
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
 
/********************************************************************//**
2689
1995
Find out if a buffer block was created by buf_chunk_init().
2690
1996
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
2691
1997
static
2692
1998
ibool
2693
1999
buf_block_is_uncompressed(
2694
2000
/*======================*/
2695
 
        buf_pool_t*             buf_pool,       /*!< in: buffer pool instance */
2696
 
        const buf_block_t*      block)          /*!< in: pointer to block,
2697
 
                                                not dereferenced */
 
2001
        const buf_block_t*      block)  /*!< in: pointer to block,
 
2002
                                        not dereferenced */
2698
2003
{
2699
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2004
        ut_ad(buf_pool_mutex_own());
2700
2005
 
2701
2006
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2702
2007
                /* The pointer should be aligned. */
2703
2008
                return(FALSE);
2704
2009
        }
2705
2010
 
2706
 
        return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
 
2011
        return(buf_pointer_is_block_field((void *)block));
2707
2012
}
2708
2013
 
2709
2014
/********************************************************************//**
2720
2025
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2721
2026
        buf_block_t*    guess,  /*!< in: guessed block or NULL */
2722
2027
        ulint           mode,   /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2723
 
                                BUF_GET_NO_LATCH, or
2724
 
                                BUF_GET_IF_IN_POOL_OR_WATCH */
 
2028
                                BUF_GET_NO_LATCH */
2725
2029
        const char*     file,   /*!< in: file name */
2726
2030
        ulint           line,   /*!< in: line where called */
2727
2031
        mtr_t*          mtr)    /*!< in: mini-transaction */
2728
2032
{
2729
2033
        buf_block_t*    block;
2730
 
        ulint           fold;
2731
2034
        unsigned        access_time;
2732
2035
        ulint           fix_type;
2733
2036
        ibool           must_read;
2734
 
        ulint           retries = 0;
2735
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2736
2037
 
2737
2038
        ut_ad(mtr);
2738
 
        ut_ad(mtr->state == MTR_ACTIVE);
2739
2039
        ut_ad((rw_latch == RW_S_LATCH)
2740
2040
              || (rw_latch == RW_X_LATCH)
2741
2041
              || (rw_latch == RW_NO_LATCH));
2742
2042
        ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_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);
 
2043
        ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
 
2044
              || (mode == BUF_GET_NO_LATCH));
2747
2045
        ut_ad(zip_size == fil_space_get_zip_size(space));
2748
2046
        ut_ad(ut_is_2pow(zip_size));
2749
2047
#ifndef UNIV_LOG_DEBUG
2750
2048
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2751
2049
#endif
2752
2050
        buf_pool->stat.n_page_gets++;
2753
 
        fold = buf_page_address_fold(space, offset);
2754
2051
loop:
2755
2052
        block = guess;
2756
 
        buf_pool_mutex_enter(buf_pool);
 
2053
        buf_pool_mutex_enter();
2757
2054
 
2758
2055
        if (block) {
2759
2056
                /* If the guess is a compressed page descriptor that
2764
2061
                the guess may be pointing to a buffer pool chunk that
2765
2062
                has been released when resizing the buffer pool. */
2766
2063
 
2767
 
                if (!buf_block_is_uncompressed(buf_pool, block)
 
2064
                if (!buf_block_is_uncompressed(block)
2768
2065
                    || offset != block->page.offset
2769
2066
                    || space != block->page.space
2770
2067
                    || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2777
2074
        }
2778
2075
 
2779
2076
        if (block == NULL) {
2780
 
                block = (buf_block_t*) buf_page_hash_get_low(
2781
 
                        buf_pool, space, offset, fold);
 
2077
                block = (buf_block_t*) buf_page_hash_get(space, offset);
2782
2078
        }
2783
2079
 
2784
2080
loop2:
2785
 
        if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2786
 
                block = NULL;
2787
 
        }
2788
 
 
2789
2081
        if (block == NULL) {
2790
2082
                /* Page not in buf_pool: needs to be read from file */
2791
2083
 
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) {
 
2084
                buf_pool_mutex_exit();
 
2085
 
 
2086
                if (mode == BUF_GET_IF_IN_POOL) {
2806
2087
 
2807
2088
                        return(NULL);
2808
2089
                }
2809
2090
 
2810
 
                if (buf_read_page(space, zip_size, offset)) {
2811
 
                        retries = 0;
2812
 
                } else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
2813
 
                        ++retries;
2814
 
                } else {
2815
 
                        fprintf(stderr, "InnoDB: Error: Unable"
2816
 
                                " to read tablespace %lu page no"
2817
 
                                " %lu into the buffer pool after"
2818
 
                                " %lu attempts\n"
2819
 
                                "InnoDB: The most probable cause"
2820
 
                                " of this error may be that the"
2821
 
                                " table has been corrupted.\n"
2822
 
                                "InnoDB: You can try to fix this"
2823
 
                                " problem by using"
2824
 
                                " innodb_force_recovery.\n"
2825
 
                                "InnoDB: Please see reference manual"
2826
 
                                " for more details.\n"
2827
 
                                "InnoDB: Aborting...\n",
2828
 
                                space, offset,
2829
 
                                BUF_PAGE_READ_MAX_RETRIES);
2830
 
 
2831
 
                        ut_error;
2832
 
                }
 
2091
                buf_read_page(space, zip_size, offset);
2833
2092
 
2834
2093
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2835
2094
                ut_a(++buf_dbg_counter % 37 || buf_validate());
2837
2096
                goto loop;
2838
2097
        }
2839
2098
 
2840
 
got_block:
2841
2099
        ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
2842
2100
 
2843
2101
        must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
2844
2102
 
2845
2103
        if (must_read && mode == BUF_GET_IF_IN_POOL) {
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);
 
2104
                /* The page is only being read to buffer */
 
2105
                buf_pool_mutex_exit();
2851
2106
 
2852
2107
                return(NULL);
2853
2108
        }
2863
2118
        case BUF_BLOCK_ZIP_DIRTY:
2864
2119
                bpage = &block->page;
2865
2120
                /* Protect bpage->buf_fix_count. */
2866
 
                mutex_enter(&buf_pool->zip_mutex);
 
2121
                mutex_enter(&buf_pool_zip_mutex);
2867
2122
 
2868
2123
                if (bpage->buf_fix_count
2869
2124
                    || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2870
2125
                        /* This condition often occurs when the buffer
2871
2126
                        is not buffer-fixed, but I/O-fixed by
2872
2127
                        buf_page_init_for_read(). */
2873
 
                        mutex_exit(&buf_pool->zip_mutex);
 
2128
                        mutex_exit(&buf_pool_zip_mutex);
2874
2129
wait_until_unfixed:
2875
2130
                        /* The block is buffer-fixed or I/O-fixed.
2876
2131
                        Try again later. */
2877
 
                        buf_pool_mutex_exit(buf_pool);
 
2132
                        buf_pool_mutex_exit();
2878
2133
                        os_thread_sleep(WAIT_FOR_READ);
2879
 
  
 
2134
 
2880
2135
                        goto loop;
2881
2136
                }
2882
2137
 
2883
2138
                /* Allocate an uncompressed page. */
2884
 
                buf_pool_mutex_exit(buf_pool);
2885
 
                mutex_exit(&buf_pool->zip_mutex);
 
2139
                buf_pool_mutex_exit();
 
2140
                mutex_exit(&buf_pool_zip_mutex);
2886
2141
 
2887
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2142
                block = buf_LRU_get_free_block(0);
2888
2143
                ut_a(block);
2889
2144
 
2890
 
                buf_pool_mutex_enter(buf_pool);
 
2145
                buf_pool_mutex_enter();
2891
2146
                mutex_enter(&block->mutex);
2892
2147
 
2893
2148
                {
2894
 
                        buf_page_t*     hash_bpage;
2895
 
 
2896
 
                        hash_bpage = buf_page_hash_get_low(
2897
 
                                buf_pool, space, offset, fold);
 
2149
                        buf_page_t*     hash_bpage
 
2150
                                = buf_page_hash_get(space, offset);
2898
2151
 
2899
2152
                        if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2900
2153
                                /* The buf_pool->page_hash was modified
2901
 
                                while buf_pool->mutex was released.
 
2154
                                while buf_pool_mutex was released.
2902
2155
                                Free the block that was allocated. */
2903
2156
 
2904
2157
                                buf_LRU_block_free_non_file_page(block);
2914
2167
                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
2915
2168
 
2916
2169
                        /* The block was buffer-fixed or I/O-fixed
2917
 
                        while buf_pool->mutex was not held by this thread.
 
2170
                        while buf_pool_mutex was not held by this thread.
2918
2171
                        Free the block that was allocated and try again.
2919
2172
                        This should be extremely unlikely. */
2920
2173
 
2927
2180
                /* Move the compressed page from bpage to block,
2928
2181
                and uncompress it. */
2929
2182
 
2930
 
                mutex_enter(&buf_pool->zip_mutex);
 
2183
                mutex_enter(&buf_pool_zip_mutex);
2931
2184
 
2932
2185
                buf_relocate(bpage, &block->page);
2933
2186
                buf_block_init_low(block);
2943
2196
                        ut_ad(!block->page.in_flush_list);
2944
2197
                } else {
2945
2198
                        /* Relocate buf_pool->flush_list. */
2946
 
                        buf_flush_relocate_on_flush_list(bpage,
2947
 
                                                         &block->page);
 
2199
                        buf_page_t*     b;
 
2200
 
 
2201
                        b = UT_LIST_GET_PREV(list, &block->page);
 
2202
                        ut_ad(block->page.in_flush_list);
 
2203
                        UT_LIST_REMOVE(list, buf_pool->flush_list,
 
2204
                                       &block->page);
 
2205
 
 
2206
                        if (b) {
 
2207
                                UT_LIST_INSERT_AFTER(
 
2208
                                        list, buf_pool->flush_list, b,
 
2209
                                        &block->page);
 
2210
                        } else {
 
2211
                                UT_LIST_ADD_FIRST(
 
2212
                                        list, buf_pool->flush_list,
 
2213
                                        &block->page);
 
2214
                        }
2948
2215
                }
2949
2216
 
2950
2217
                /* Buffer-fix, I/O-fix, and X-latch the block
2957
2224
 
2958
2225
                block->page.buf_fix_count = 1;
2959
2226
                buf_block_set_io_fix(block, BUF_IO_READ);
2960
 
                rw_lock_x_lock_func(&block->lock, 0, file, line);
2961
 
 
2962
 
                UNIV_MEM_INVALID(bpage, sizeof *bpage);
2963
 
 
 
2227
                rw_lock_x_lock(&block->lock);
2964
2228
                mutex_exit(&block->mutex);
2965
 
                mutex_exit(&buf_pool->zip_mutex);
 
2229
                mutex_exit(&buf_pool_zip_mutex);
2966
2230
                buf_pool->n_pend_unzip++;
2967
2231
 
2968
 
                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 
2232
                buf_buddy_free(bpage, sizeof *bpage);
2969
2233
 
2970
 
                buf_pool_mutex_exit(buf_pool);
 
2234
                buf_pool_mutex_exit();
2971
2235
 
2972
2236
                /* Decompress the page and apply buffered operations
2973
 
                while not holding buf_pool->mutex or block->mutex. */
 
2237
                while not holding buf_pool_mutex or block->mutex. */
2974
2238
                success = buf_zip_decompress(block, srv_use_checksums);
2975
 
                ut_a(success);
2976
2239
 
2977
 
                if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
 
2240
                if (UNIV_LIKELY(success)) {
2978
2241
                        ibuf_merge_or_delete_for_page(block, space, offset,
2979
2242
                                                      zip_size, TRUE);
2980
2243
                }
2981
2244
 
2982
2245
                /* Unfix and unlatch the block. */
2983
 
                buf_pool_mutex_enter(buf_pool);
 
2246
                buf_pool_mutex_enter();
2984
2247
                mutex_enter(&block->mutex);
2985
2248
                block->page.buf_fix_count--;
2986
2249
                buf_block_set_io_fix(block, BUF_IO_NONE);
2988
2251
                buf_pool->n_pend_unzip--;
2989
2252
                rw_lock_x_unlock(&block->lock);
2990
2253
 
 
2254
                if (UNIV_UNLIKELY(!success)) {
 
2255
 
 
2256
                        buf_pool_mutex_exit();
 
2257
                        return(NULL);
 
2258
                }
 
2259
 
2991
2260
                break;
2992
2261
 
2993
2262
        case BUF_BLOCK_ZIP_FREE:
3002
2271
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3003
2272
 
3004
2273
        mutex_enter(&block->mutex);
3005
 
#if UNIV_WORD_SIZE == 4
3006
 
        /* On 32-bit systems, there is no padding in buf_page_t.  On
3007
 
        other systems, Valgrind could complain about uninitialized pad
3008
 
        bytes. */
3009
2274
        UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
3010
 
#endif
3011
 
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
3012
 
        if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
3013
 
            && ibuf_debug) {
3014
 
                /* Try to evict the block from the buffer pool, to use the
3015
 
                insert buffer (change buffer) as much as possible. */
3016
 
 
3017
 
                if (buf_LRU_free_block(&block->page, TRUE, NULL)
3018
 
                    == BUF_LRU_FREED) {
3019
 
                        mutex_exit(&block->mutex);
3020
 
                        if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
3021
 
                                /* Set the watch, as it would have
3022
 
                                been set if the page were not in the
3023
 
                                buffer pool in the first place. */
3024
 
                                block = (buf_block_t*) buf_pool_watch_set(
3025
 
                                        space, offset, fold);
3026
 
 
3027
 
                                if (UNIV_LIKELY_NULL(block)) {
3028
 
 
3029
 
                                        /* The page entered the buffer
3030
 
                                        pool for some reason. Try to
3031
 
                                        evict it again. */
3032
 
                                        goto got_block;
3033
 
                                }
3034
 
                        }
3035
 
                        buf_pool_mutex_exit(buf_pool);
3036
 
                        fprintf(stderr,
3037
 
                                "innodb_change_buffering_debug evict %u %u\n",
3038
 
                                (unsigned) space, (unsigned) offset);
3039
 
                        return(NULL);
3040
 
                } else if (buf_flush_page_try(buf_pool, block)) {
3041
 
                        fprintf(stderr,
3042
 
                                "innodb_change_buffering_debug flush %u %u\n",
3043
 
                                (unsigned) space, (unsigned) offset);
3044
 
                        guess = block;
3045
 
                        goto loop;
3046
 
                }
3047
 
 
3048
 
                /* Failed to evict the page; change it directly */
3049
 
        }
3050
 
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
3051
2275
 
3052
2276
        buf_block_buf_fix_inc(block, file, line);
3053
2277
 
3057
2281
 
3058
2282
        access_time = buf_page_is_accessed(&block->page);
3059
2283
 
3060
 
        buf_pool_mutex_exit(buf_pool);
 
2284
        buf_pool_mutex_exit();
3061
2285
 
3062
2286
        buf_page_set_accessed_make_young(&block->page, access_time);
3063
2287
 
3132
2356
@return TRUE if success */
3133
2357
UNIV_INTERN
3134
2358
ibool
3135
 
buf_page_optimistic_get(
3136
 
/*====================*/
 
2359
buf_page_optimistic_get_func(
 
2360
/*=========================*/
3137
2361
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
3138
2362
        buf_block_t*    block,  /*!< in: guessed buffer block */
3139
2363
        ib_uint64_t     modify_clock,/*!< in: modify clock value if mode is
3142
2366
        ulint           line,   /*!< in: line where called */
3143
2367
        mtr_t*          mtr)    /*!< in: mini-transaction */
3144
2368
{
3145
 
        buf_pool_t*     buf_pool;
3146
2369
        unsigned        access_time;
3147
2370
        ibool           success;
3148
2371
        ulint           fix_type;
3149
2372
 
3150
 
        ut_ad(block);
3151
 
        ut_ad(mtr);
3152
 
        ut_ad(mtr->state == MTR_ACTIVE);
 
2373
        ut_ad(mtr && block);
3153
2374
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3154
2375
 
3155
2376
        mutex_enter(&block->mutex);
3236
2457
        ut_a(ibuf_count_get(buf_block_get_space(block),
3237
2458
                            buf_block_get_page_no(block)) == 0);
3238
2459
#endif
3239
 
        buf_pool = buf_pool_from_block(block);
3240
2460
        buf_pool->stat.n_page_gets++;
3241
2461
 
3242
2462
        return(TRUE);
3258
2478
        ulint           line,   /*!< in: line where called */
3259
2479
        mtr_t*          mtr)    /*!< in: mini-transaction */
3260
2480
{
3261
 
        buf_pool_t*     buf_pool;
3262
2481
        ibool           success;
3263
2482
        ulint           fix_type;
3264
2483
 
3265
2484
        ut_ad(mtr);
3266
 
        ut_ad(mtr->state == MTR_ACTIVE);
3267
2485
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3268
2486
 
3269
2487
        mutex_enter(&block->mutex);
3287
2505
 
3288
2506
        mutex_exit(&block->mutex);
3289
2507
 
3290
 
        buf_pool = buf_pool_from_block(block);
3291
 
 
3292
2508
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
3293
 
                buf_pool_mutex_enter(buf_pool);
 
2509
                buf_pool_mutex_enter();
3294
2510
                buf_LRU_make_block_young(&block->page);
3295
 
                buf_pool_mutex_exit(buf_pool);
 
2511
                buf_pool_mutex_exit();
3296
2512
        } else if (!buf_page_is_accessed(&block->page)) {
3297
2513
                /* Above, we do a dirty read on purpose, to avoid
3298
2514
                mutex contention.  The field buf_page_t::access_time
3300
2516
                field must be protected by mutex, however. */
3301
2517
                ulint   time_ms = ut_time_ms();
3302
2518
 
3303
 
                buf_pool_mutex_enter(buf_pool);
 
2519
                buf_pool_mutex_enter();
3304
2520
                buf_page_set_accessed(&block->page, time_ms);
3305
 
                buf_pool_mutex_exit(buf_pool);
 
2521
                buf_pool_mutex_exit();
3306
2522
        }
3307
2523
 
3308
2524
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
3364
2580
        buf_block_t*    block;
3365
2581
        ibool           success;
3366
2582
        ulint           fix_type;
3367
 
        buf_pool_t*     buf_pool = buf_pool_get(space_id, page_no);
3368
 
 
3369
 
        ut_ad(mtr);
3370
 
        ut_ad(mtr->state == MTR_ACTIVE);
3371
 
 
3372
 
        buf_pool_mutex_enter(buf_pool);
3373
 
        block = buf_block_hash_get(buf_pool, space_id, page_no);
3374
 
 
3375
 
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
3376
 
                buf_pool_mutex_exit(buf_pool);
 
2583
 
 
2584
        buf_pool_mutex_enter();
 
2585
        block = buf_block_hash_get(space_id, page_no);
 
2586
 
 
2587
        if (!block) {
 
2588
                buf_pool_mutex_exit();
3377
2589
                return(NULL);
3378
2590
        }
3379
2591
 
3380
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
3381
 
 
3382
2592
        mutex_enter(&block->mutex);
3383
 
        buf_pool_mutex_exit(buf_pool);
 
2593
        buf_pool_mutex_exit();
3384
2594
 
3385
2595
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3386
2596
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3463
2673
        ulint           space,  /*!< in: space id */
3464
2674
        ulint           offset, /*!< in: offset of the page within space
3465
2675
                                in units of a page */
3466
 
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
3467
2676
        buf_block_t*    block)  /*!< in: block to init */
3468
2677
{
3469
2678
        buf_page_t*     hash_page;
3470
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3471
2679
 
3472
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2680
        ut_ad(buf_pool_mutex_own());
3473
2681
        ut_ad(mutex_own(&(block->mutex)));
3474
2682
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
3475
2683
 
3487
2695
 
3488
2696
        buf_block_init_low(block);
3489
2697
 
3490
 
        block->lock_hash_val = lock_rec_hash(space, offset);
3491
 
 
3492
 
        buf_page_init_low(&block->page);
 
2698
        block->lock_hash_val    = lock_rec_hash(space, offset);
3493
2699
 
3494
2700
        /* Insert into the hash table of file pages */
3495
2701
 
3496
 
        hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
3497
 
 
3498
 
        if (UNIV_LIKELY(!hash_page)) {
3499
 
        } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
3500
 
                /* Preserve the reference count. */
3501
 
                ulint   buf_fix_count = hash_page->buf_fix_count;
3502
 
 
3503
 
                ut_a(buf_fix_count > 0);
3504
 
                block->page.buf_fix_count += buf_fix_count;
3505
 
                buf_pool_watch_remove(buf_pool, fold, hash_page);
3506
 
        } else {
 
2702
        hash_page = buf_page_hash_get(space, offset);
 
2703
 
 
2704
        if (UNIV_LIKELY_NULL(hash_page)) {
3507
2705
                fprintf(stderr,
3508
2706
                        "InnoDB: Error: page %lu %lu already found"
3509
2707
                        " in the hash table: %p, %p\n",
3512
2710
                        (const void*) hash_page, (const void*) block);
3513
2711
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3514
2712
                mutex_exit(&block->mutex);
3515
 
                buf_pool_mutex_exit(buf_pool);
 
2713
                buf_pool_mutex_exit();
3516
2714
                buf_print();
3517
2715
                buf_LRU_print();
3518
2716
                buf_validate();
3521
2719
                ut_error;
3522
2720
        }
3523
2721
 
 
2722
        buf_page_init_low(&block->page);
 
2723
 
3524
2724
        ut_ad(!block->page.in_zip_hash);
3525
2725
        ut_ad(!block->page.in_page_hash);
3526
2726
        ut_d(block->page.in_page_hash = TRUE);
3527
2727
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
3528
 
                    fold, &block->page);
 
2728
                    buf_page_address_fold(space, offset), &block->page);
3529
2729
}
3530
2730
 
3531
2731
/********************************************************************//**
3547
2747
        ulint           space,  /*!< in: space id */
3548
2748
        ulint           zip_size,/*!< in: compressed page size, or 0 */
3549
2749
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
3550
 
        ib_int64_t      tablespace_version,
3551
 
                                /*!< in: prevents reading from a wrong
 
2750
        ib_int64_t      tablespace_version,/*!< in: prevents reading from a wrong
3552
2751
                                version of the tablespace in case we have done
3553
2752
                                DISCARD + IMPORT */
3554
2753
        ulint           offset) /*!< in: page number */
3555
2754
{
3556
2755
        buf_block_t*    block;
3557
 
        buf_page_t*     bpage   = NULL;
3558
 
        buf_page_t*     watch_page;
 
2756
        buf_page_t*     bpage;
3559
2757
        mtr_t           mtr;
3560
 
        ulint           fold;
3561
2758
        ibool           lru     = FALSE;
3562
2759
        void*           data;
3563
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3564
2760
 
3565
2761
        ut_ad(buf_pool);
3566
2762
 
3589
2785
            && UNIV_LIKELY(!recv_recovery_is_on())) {
3590
2786
                block = NULL;
3591
2787
        } else {
3592
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2788
                block = buf_LRU_get_free_block(0);
3593
2789
                ut_ad(block);
3594
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
3595
2790
        }
3596
2791
 
3597
 
        fold = buf_page_address_fold(space, offset);
3598
 
 
3599
 
        buf_pool_mutex_enter(buf_pool);
3600
 
 
3601
 
        watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
3602
 
        if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
 
2792
        buf_pool_mutex_enter();
 
2793
 
 
2794
        if (buf_page_hash_get(space, offset)) {
3603
2795
                /* The page is already in the buffer pool. */
3604
 
                watch_page = NULL;
3605
2796
err_exit:
3606
2797
                if (block) {
3607
2798
                        mutex_enter(&block->mutex);
3625
2816
        if (block) {
3626
2817
                bpage = &block->page;
3627
2818
                mutex_enter(&block->mutex);
3628
 
 
3629
 
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
3630
 
 
3631
 
                buf_page_init(space, offset, fold, block);
 
2819
                buf_page_init(space, offset, block);
3632
2820
 
3633
2821
                /* The block must be put to the LRU list, to the old blocks */
3634
2822
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3648
2836
                if (UNIV_UNLIKELY(zip_size)) {
3649
2837
                        page_zip_set_size(&block->page.zip, zip_size);
3650
2838
 
3651
 
                        /* buf_pool->mutex may be released and
 
2839
                        /* buf_pool_mutex may be released and
3652
2840
                        reacquired by buf_buddy_alloc().  Thus, we
3653
2841
                        must release block->mutex in order not to
3654
2842
                        break the latching order in the reacquisition
3655
 
                        of buf_pool->mutex.  We also must defer this
 
2843
                        of buf_pool_mutex.  We also must defer this
3656
2844
                        operation until after the block descriptor has
3657
2845
                        been added to buf_pool->LRU and
3658
2846
                        buf_pool->page_hash. */
3659
2847
                        mutex_exit(&block->mutex);
3660
 
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2848
                        data = buf_buddy_alloc(zip_size, &lru);
3661
2849
                        mutex_enter(&block->mutex);
3662
 
                        block->page.zip.data = static_cast<unsigned char *>(data);
 
2850
                        block->page.zip.data = data;
3663
2851
 
3664
2852
                        /* To maintain the invariant
3665
2853
                        block->in_unzip_LRU_list
3681
2869
                control block (bpage), in order to avoid the
3682
2870
                invocation of buf_buddy_relocate_block() on
3683
2871
                uninitialized data. */
3684
 
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3685
 
                bpage = static_cast<buf_page_struct *>(buf_buddy_alloc(buf_pool, sizeof *bpage, &lru));
3686
 
 
3687
 
                /* Initialize the buf_pool pointer. */
3688
 
                bpage->buf_pool_index = buf_pool_index(buf_pool);
 
2872
                data = buf_buddy_alloc(zip_size, &lru);
 
2873
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3689
2874
 
3690
2875
                /* If buf_buddy_alloc() allocated storage from the LRU list,
3691
 
                it released and reacquired buf_pool->mutex.  Thus, we must
 
2876
                it released and reacquired buf_pool_mutex.  Thus, we must
3692
2877
                check the page_hash again, as it may have been modified. */
3693
 
                if (UNIV_UNLIKELY(lru)) {
3694
 
 
3695
 
                        watch_page = buf_page_hash_get_low(
3696
 
                                buf_pool, space, offset, fold);
3697
 
 
3698
 
                        if (watch_page
3699
 
                            && !buf_pool_watch_is_sentinel(buf_pool,
3700
 
                                                           watch_page)) {
3701
 
 
3702
 
                                /* The block was added by some other thread. */
3703
 
                                watch_page = NULL;
3704
 
                                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
3705
 
                                buf_buddy_free(buf_pool, data, zip_size);
3706
 
 
3707
 
                                bpage = NULL;
3708
 
                                goto func_exit;
3709
 
                        }
 
2878
                if (UNIV_UNLIKELY(lru)
 
2879
                    && UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
 
2880
 
 
2881
                        /* The block was added by some other thread. */
 
2882
                        buf_buddy_free(bpage, sizeof *bpage);
 
2883
                        buf_buddy_free(data, zip_size);
 
2884
 
 
2885
                        bpage = NULL;
 
2886
                        goto func_exit;
3710
2887
                }
3711
2888
 
3712
2889
                page_zip_des_init(&bpage->zip);
3713
2890
                page_zip_set_size(&bpage->zip, zip_size);
3714
 
                bpage->zip.data = static_cast<unsigned char *>(data);
 
2891
                bpage->zip.data = data;
3715
2892
 
3716
 
                mutex_enter(&buf_pool->zip_mutex);
 
2893
                mutex_enter(&buf_pool_zip_mutex);
3717
2894
                UNIV_MEM_DESC(bpage->zip.data,
3718
2895
                              page_zip_get_size(&bpage->zip), bpage);
3719
 
 
3720
2896
                buf_page_init_low(bpage);
3721
 
 
3722
2897
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
3723
2898
                bpage->space    = space;
3724
2899
                bpage->offset   = offset;
3725
2900
 
3726
 
 
3727
2901
#ifdef UNIV_DEBUG
3728
2902
                bpage->in_page_hash = FALSE;
3729
2903
                bpage->in_zip_hash = FALSE;
3733
2907
#endif /* UNIV_DEBUG */
3734
2908
 
3735
2909
                ut_d(bpage->in_page_hash = TRUE);
3736
 
 
3737
 
                if (UNIV_LIKELY_NULL(watch_page)) {
3738
 
                        /* Preserve the reference count. */
3739
 
                        ulint   buf_fix_count = watch_page->buf_fix_count;
3740
 
                        ut_a(buf_fix_count > 0);
3741
 
                        bpage->buf_fix_count += buf_fix_count;
3742
 
                        ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
3743
 
                        buf_pool_watch_remove(buf_pool, fold, watch_page);
3744
 
                }
3745
 
 
3746
 
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
3747
 
                            bpage);
 
2910
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
2911
                            buf_page_address_fold(space, offset), bpage);
3748
2912
 
3749
2913
                /* The block must be put to the LRU list, to the old blocks */
3750
2914
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3752
2916
 
3753
2917
                buf_page_set_io_fix(bpage, BUF_IO_READ);
3754
2918
 
3755
 
                mutex_exit(&buf_pool->zip_mutex);
 
2919
                mutex_exit(&buf_pool_zip_mutex);
3756
2920
        }
3757
2921
 
3758
2922
        buf_pool->n_pend_reads++;
3759
2923
func_exit:
3760
 
        buf_pool_mutex_exit(buf_pool);
 
2924
        buf_pool_mutex_exit();
3761
2925
 
3762
2926
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
3763
2927
 
3786
2950
{
3787
2951
        buf_frame_t*    frame;
3788
2952
        buf_block_t*    block;
3789
 
        ulint           fold;
3790
2953
        buf_block_t*    free_block      = NULL;
3791
2954
        ulint           time_ms         = ut_time_ms();
3792
 
        buf_pool_t*     buf_pool        = buf_pool_get(space, offset);
3793
2955
 
3794
2956
        ut_ad(mtr);
3795
 
        ut_ad(mtr->state == MTR_ACTIVE);
3796
2957
        ut_ad(space || !zip_size);
3797
2958
 
3798
 
        free_block = buf_LRU_get_free_block(buf_pool, 0);
3799
 
 
3800
 
        fold = buf_page_address_fold(space, offset);
3801
 
 
3802
 
        buf_pool_mutex_enter(buf_pool);
3803
 
 
3804
 
        block = (buf_block_t*) buf_page_hash_get_low(
3805
 
                buf_pool, space, offset, fold);
3806
 
 
3807
 
        if (block
3808
 
            && buf_page_in_file(&block->page)
3809
 
            && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
 
2959
        free_block = buf_LRU_get_free_block(0);
 
2960
 
 
2961
        buf_pool_mutex_enter();
 
2962
 
 
2963
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2964
 
 
2965
        if (block && buf_page_in_file(&block->page)) {
3810
2966
#ifdef UNIV_IBUF_COUNT_DEBUG
3811
2967
                ut_a(ibuf_count_get(space, offset) == 0);
3812
2968
#endif
3815
2971
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3816
2972
 
3817
2973
                /* Page can be found in buf_pool */
3818
 
                buf_pool_mutex_exit(buf_pool);
 
2974
                buf_pool_mutex_exit();
3819
2975
 
3820
2976
                buf_block_free(free_block);
3821
2977
 
3836
2992
 
3837
2993
        mutex_enter(&block->mutex);
3838
2994
 
3839
 
        buf_page_init(space, offset, fold, block);
 
2995
        buf_page_init(space, offset, block);
3840
2996
 
3841
2997
        /* The block must be put to the LRU list */
3842
2998
        buf_LRU_add_block(&block->page, FALSE);
3849
3005
                ibool   lru;
3850
3006
 
3851
3007
                /* Prevent race conditions during buf_buddy_alloc(),
3852
 
                which may release and reacquire buf_pool->mutex,
 
3008
                which may release and reacquire buf_pool_mutex,
3853
3009
                by IO-fixing and X-latching the block. */
3854
3010
 
3855
3011
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3857
3013
 
3858
3014
                page_zip_set_size(&block->page.zip, zip_size);
3859
3015
                mutex_exit(&block->mutex);
3860
 
                /* buf_pool->mutex may be released and reacquired by
 
3016
                /* buf_pool_mutex may be released and reacquired by
3861
3017
                buf_buddy_alloc().  Thus, we must release block->mutex
3862
3018
                in order not to break the latching order in
3863
 
                the reacquisition of buf_pool->mutex.  We also must
 
3019
                the reacquisition of buf_pool_mutex.  We also must
3864
3020
                defer this operation until after the block descriptor
3865
3021
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3866
 
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
3022
                data = buf_buddy_alloc(zip_size, &lru);
3867
3023
                mutex_enter(&block->mutex);
3868
 
                block->page.zip.data = static_cast<unsigned char *>(data);
 
3024
                block->page.zip.data = data;
3869
3025
 
3870
3026
                /* To maintain the invariant
3871
3027
                block->in_unzip_LRU_list
3881
3037
 
3882
3038
        buf_page_set_accessed(&block->page, time_ms);
3883
3039
 
3884
 
        buf_pool_mutex_exit(buf_pool);
 
3040
        buf_pool_mutex_exit();
3885
3041
 
3886
3042
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3887
3043
 
3893
3049
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3894
3050
 
3895
3051
        /* Flush pages from the end of the LRU list if necessary */
3896
 
        buf_flush_free_margin(buf_pool);
 
3052
        buf_flush_free_margin();
3897
3053
 
3898
3054
        frame = block->frame;
3899
3055
 
3929
3085
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
3930
3086
{
3931
3087
        enum buf_io_fix io_type;
3932
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3933
3088
        const ibool     uncompressed = (buf_page_get_state(bpage)
3934
3089
                                        == BUF_BLOCK_FILE_PAGE);
3935
3090
 
4065
3220
                }
4066
3221
        }
4067
3222
 
4068
 
        buf_pool_mutex_enter(buf_pool);
 
3223
        buf_pool_mutex_enter();
4069
3224
        mutex_enter(buf_page_get_mutex(bpage));
4070
3225
 
4071
3226
#ifdef UNIV_IBUF_COUNT_DEBUG
4129
3284
#endif /* UNIV_DEBUG */
4130
3285
 
4131
3286
        mutex_exit(buf_page_get_mutex(bpage));
4132
 
        buf_pool_mutex_exit(buf_pool);
4133
 
}
4134
 
 
4135
 
/*********************************************************************//**
4136
 
Asserts that all file pages in the buffer are in a replaceable state.
4137
 
@return TRUE */
4138
 
static
4139
 
ibool
4140
 
buf_all_freed_instance(
4141
 
/*===================*/
4142
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instancce */
4143
 
{
4144
 
        ulint           i;
4145
 
        buf_chunk_t*    chunk;
4146
 
 
4147
 
        ut_ad(buf_pool);
4148
 
 
4149
 
        buf_pool_mutex_enter(buf_pool);
4150
 
 
4151
 
        chunk = buf_pool->chunks;
4152
 
 
4153
 
        for (i = buf_pool->n_chunks; i--; chunk++) {
4154
 
 
4155
 
                const buf_block_t* block = buf_chunk_not_freed(chunk);
4156
 
 
4157
 
                if (UNIV_LIKELY_NULL(block)) {
4158
 
                        fprintf(stderr,
4159
 
                                "Page %lu %lu still fixed or dirty\n",
4160
 
                                (ulong) block->page.space,
4161
 
                                (ulong) block->page.offset);
4162
 
                        ut_error;
4163
 
                }
4164
 
        }
4165
 
 
4166
 
        buf_pool_mutex_exit(buf_pool);
4167
 
 
4168
 
        return(TRUE);
4169
 
}
4170
 
 
4171
 
/*********************************************************************//**
4172
 
Invalidates file pages in one buffer pool instance */
4173
 
static
 
3287
        buf_pool_mutex_exit();
 
3288
}
 
3289
 
 
3290
/*********************************************************************//**
 
3291
Invalidates the file pages in the buffer pool when an archive recovery is
 
3292
completed. All the file pages buffered must be in a replaceable state when
 
3293
this function is called: not latched and not modified. */
 
3294
UNIV_INTERN
4174
3295
void
4175
 
buf_pool_invalidate_instance(
4176
 
/*=========================*/
4177
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3296
buf_pool_invalidate(void)
 
3297
/*=====================*/
4178
3298
{
4179
3299
        ibool           freed;
4180
 
        int     i;
 
3300
        enum buf_flush  i;
4181
3301
 
4182
 
        buf_pool_mutex_enter(buf_pool);
 
3302
        buf_pool_mutex_enter();
4183
3303
 
4184
3304
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
4185
3305
 
4195
3315
                pool invalidation to proceed we must ensure there is NO
4196
3316
                write activity happening. */
4197
3317
                if (buf_pool->n_flush[i] > 0) {
4198
 
                        buf_pool_mutex_exit(buf_pool);
4199
 
                        buf_flush_wait_batch_end(buf_pool, static_cast<buf_flush>(i));
4200
 
                        buf_pool_mutex_enter(buf_pool);
 
3318
                        buf_pool_mutex_exit();
 
3319
                        buf_flush_wait_batch_end(i);
 
3320
                        buf_pool_mutex_enter();
4201
3321
                }
4202
3322
        }
4203
3323
 
4204
 
        buf_pool_mutex_exit(buf_pool);
 
3324
        buf_pool_mutex_exit();
4205
3325
 
4206
 
        ut_ad(buf_all_freed_instance(buf_pool));
 
3326
        ut_ad(buf_all_freed());
4207
3327
 
4208
3328
        freed = TRUE;
4209
3329
 
4210
3330
        while (freed) {
4211
 
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
 
3331
                freed = buf_LRU_search_and_free_block(100);
4212
3332
        }
4213
3333
 
4214
 
        buf_pool_mutex_enter(buf_pool);
 
3334
        buf_pool_mutex_enter();
4215
3335
 
4216
3336
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
4217
3337
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
4222
3342
        buf_pool->LRU_flush_ended = 0;
4223
3343
 
4224
3344
        memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
4225
 
        buf_refresh_io_stats(buf_pool);
4226
 
 
4227
 
        buf_pool_mutex_exit(buf_pool);
4228
 
}
4229
 
 
4230
 
/*********************************************************************//**
4231
 
Invalidates the file pages in the buffer pool when an archive recovery is
4232
 
completed. All the file pages buffered must be in a replaceable state when
4233
 
this function is called: not latched and not modified. */
4234
 
UNIV_INTERN
4235
 
void
4236
 
buf_pool_invalidate(void)
4237
 
/*=====================*/
4238
 
{
4239
 
        ulint   i;
4240
 
 
4241
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4242
 
                buf_pool_invalidate_instance(buf_pool_from_array(i));
4243
 
        }
 
3345
        buf_refresh_io_stats();
 
3346
 
 
3347
        buf_pool_mutex_exit();
4244
3348
}
4245
3349
 
4246
3350
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4247
3351
/*********************************************************************//**
4248
 
Validates data in one buffer pool instance
 
3352
Validates the buffer buf_pool data structure.
4249
3353
@return TRUE */
4250
 
static
 
3354
UNIV_INTERN
4251
3355
ibool
4252
 
buf_pool_validate_instance(
4253
 
/*=======================*/
4254
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3356
buf_validate(void)
 
3357
/*==============*/
4255
3358
{
4256
3359
        buf_page_t*     b;
4257
3360
        buf_chunk_t*    chunk;
4266
3369
 
4267
3370
        ut_ad(buf_pool);
4268
3371
 
4269
 
        buf_pool_mutex_enter(buf_pool);
 
3372
        buf_pool_mutex_enter();
4270
3373
 
4271
3374
        chunk = buf_pool->chunks;
4272
3375
 
4291
3394
                                break;
4292
3395
 
4293
3396
                        case BUF_BLOCK_FILE_PAGE:
4294
 
                                ut_a(buf_page_hash_get(buf_pool,
4295
 
                                                       buf_block_get_space(
 
3397
                                ut_a(buf_page_hash_get(buf_block_get_space(
4296
3398
                                                               block),
4297
3399
                                                       buf_block_get_page_no(
4298
3400
                                                               block))
4339
3441
                                }
4340
3442
 
4341
3443
                                n_lru++;
 
3444
 
 
3445
                                if (block->page.oldest_modification > 0) {
 
3446
                                        n_flush++;
 
3447
                                }
 
3448
 
4342
3449
                                break;
4343
3450
 
4344
3451
                        case BUF_BLOCK_NOT_USED:
4356
3463
                }
4357
3464
        }
4358
3465
 
4359
 
        mutex_enter(&buf_pool->zip_mutex);
 
3466
        mutex_enter(&buf_pool_zip_mutex);
4360
3467
 
4361
3468
        /* Check clean compressed-only blocks. */
4362
3469
 
4377
3484
                        ut_error;
4378
3485
                        break;
4379
3486
                }
4380
 
 
4381
 
                /* It is OK to read oldest_modification here because
4382
 
                we have acquired buf_pool->zip_mutex above which acts
4383
 
                as the 'block->mutex' for these bpages. */
4384
3487
                ut_a(!b->oldest_modification);
4385
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3488
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4386
3489
 
4387
3490
                n_lru++;
4388
3491
                n_zip++;
4389
3492
        }
4390
3493
 
4391
 
        /* Check dirty blocks. */
 
3494
        /* Check dirty compressed-only blocks. */
4392
3495
 
4393
 
        buf_flush_list_mutex_enter(buf_pool);
4394
3496
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4395
3497
             b = UT_LIST_GET_NEXT(list, b)) {
4396
3498
                ut_ad(b->in_flush_list);
4397
 
                ut_a(b->oldest_modification);
4398
 
                n_flush++;
4399
3499
 
4400
3500
                switch (buf_page_get_state(b)) {
4401
3501
                case BUF_BLOCK_ZIP_DIRTY:
 
3502
                        ut_a(b->oldest_modification);
4402
3503
                        n_lru++;
 
3504
                        n_flush++;
4403
3505
                        n_zip++;
4404
3506
                        switch (buf_page_get_io_fix(b)) {
4405
3507
                        case BUF_IO_NONE:
4406
3508
                        case BUF_IO_READ:
4407
3509
                                break;
 
3510
 
4408
3511
                        case BUF_IO_WRITE:
4409
3512
                                switch (buf_page_get_flush_type(b)) {
4410
3513
                                case BUF_FLUSH_LRU:
4434
3537
                        ut_error;
4435
3538
                        break;
4436
3539
                }
4437
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3540
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4438
3541
        }
4439
3542
 
4440
 
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4441
 
 
4442
 
        buf_flush_list_mutex_exit(buf_pool);
4443
 
 
4444
 
        mutex_exit(&buf_pool->zip_mutex);
 
3543
        mutex_exit(&buf_pool_zip_mutex);
4445
3544
 
4446
3545
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
4447
3546
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
4457
3556
                        (ulong) n_free);
4458
3557
                ut_error;
4459
3558
        }
 
3559
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4460
3560
 
4461
3561
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
4462
3562
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
4463
3563
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
4464
3564
 
4465
 
        buf_pool_mutex_exit(buf_pool);
 
3565
        buf_pool_mutex_exit();
4466
3566
 
4467
3567
        ut_a(buf_LRU_validate());
4468
 
        ut_a(buf_flush_validate(buf_pool));
4469
 
 
4470
 
        return(TRUE);
4471
 
}
4472
 
 
4473
 
/*********************************************************************//**
4474
 
Validates the buffer buf_pool data structure.
4475
 
@return TRUE */
4476
 
UNIV_INTERN
4477
 
ibool
4478
 
buf_validate(void)
4479
 
/*==============*/
4480
 
{
4481
 
        ulint   i;
4482
 
 
4483
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4484
 
                buf_pool_t*     buf_pool;
4485
 
 
4486
 
                buf_pool = buf_pool_from_array(i);
4487
 
 
4488
 
                buf_pool_validate_instance(buf_pool);
4489
 
        }
4490
 
        return(TRUE);
4491
 
}
4492
 
 
 
3568
        ut_a(buf_flush_validate());
 
3569
 
 
3570
        return(TRUE);
 
3571
}
4493
3572
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
4494
3573
 
4495
3574
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4496
3575
/*********************************************************************//**
4497
 
Prints info of the buffer buf_pool data structure for one instance. */
4498
 
static
 
3576
Prints info of the buffer buf_pool data structure. */
 
3577
UNIV_INTERN
4499
3578
void
4500
 
buf_print_instance(
4501
 
/*===============*/
4502
 
        buf_pool_t*     buf_pool)
 
3579
buf_print(void)
 
3580
/*===========*/
4503
3581
{
4504
 
        index_id_t*     index_ids;
 
3582
        dulint*         index_ids;
4505
3583
        ulint*          counts;
4506
3584
        ulint           size;
4507
3585
        ulint           i;
4508
3586
        ulint           j;
4509
 
        index_id_t      id;
 
3587
        dulint          id;
4510
3588
        ulint           n_found;
4511
3589
        buf_chunk_t*    chunk;
4512
3590
        dict_index_t*   index;
4515
3593
 
4516
3594
        size = buf_pool->curr_size;
4517
3595
 
4518
 
        index_ids = mem_alloc(size * sizeof *index_ids);
 
3596
        index_ids = mem_alloc(sizeof(dulint) * size);
4519
3597
        counts = mem_alloc(sizeof(ulint) * size);
4520
3598
 
4521
 
        buf_pool_mutex_enter(buf_pool);
4522
 
        buf_flush_list_mutex_enter(buf_pool);
 
3599
        buf_pool_mutex_enter();
4523
3600
 
4524
3601
        fprintf(stderr,
4525
3602
                "buf_pool size %lu\n"
4546
3623
                (ulong) buf_pool->stat.n_pages_created,
4547
3624
                (ulong) buf_pool->stat.n_pages_written);
4548
3625
 
4549
 
        buf_flush_list_mutex_exit(buf_pool);
4550
 
 
4551
3626
        /* Count the number of blocks belonging to each index in the buffer */
4552
3627
 
4553
3628
        n_found = 0;
4570
3645
 
4571
3646
                                while (j < n_found) {
4572
3647
 
4573
 
                                        if (index_ids[j] == id) {
 
3648
                                        if (ut_dulint_cmp(index_ids[j],
 
3649
                                                          id) == 0) {
4574
3650
                                                counts[j]++;
4575
3651
 
4576
3652
                                                break;
4587
3663
                }
4588
3664
        }
4589
3665
 
4590
 
        buf_pool_mutex_exit(buf_pool);
 
3666
        buf_pool_mutex_exit();
4591
3667
 
4592
3668
        for (i = 0; i < n_found; i++) {
4593
3669
                index = dict_index_get_if_in_cache(index_ids[i]);
4594
3670
 
4595
3671
                fprintf(stderr,
4596
 
                        "Block count for index %llu in buffer is about %lu",
4597
 
                        (ullint) index_ids[i],
 
3672
                        "Block count for index %lu in buffer is about %lu",
 
3673
                        (ulong) ut_dulint_get_low(index_ids[i]),
4598
3674
                        (ulong) counts[i]);
4599
3675
 
4600
3676
                if (index) {
4608
3684
        mem_free(index_ids);
4609
3685
        mem_free(counts);
4610
3686
 
4611
 
        ut_a(buf_pool_validate_instance(buf_pool));
4612
 
}
4613
 
 
4614
 
/*********************************************************************//**
4615
 
Prints info of the buffer buf_pool data structure. */
4616
 
UNIV_INTERN
4617
 
void
4618
 
buf_print(void)
4619
 
/*===========*/
4620
 
{
4621
 
        ulint   i;
4622
 
 
4623
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4624
 
                buf_pool_t*     buf_pool;
4625
 
 
4626
 
                buf_pool = buf_pool_from_array(i);
4627
 
                buf_print_instance(buf_pool);
4628
 
        }
 
3687
        ut_a(buf_validate());
4629
3688
}
4630
3689
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
4631
3690
 
4635
3694
@return number of latched pages */
4636
3695
UNIV_INTERN
4637
3696
ulint
4638
 
buf_get_latched_pages_number_instance(
4639
 
/*==================================*/
4640
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3697
buf_get_latched_pages_number(void)
 
3698
/*==============================*/
4641
3699
{
 
3700
        buf_chunk_t*    chunk;
4642
3701
        buf_page_t*     b;
4643
3702
        ulint           i;
4644
 
        buf_chunk_t*    chunk;
4645
3703
        ulint           fixed_pages_number = 0;
4646
3704
 
4647
 
        buf_pool_mutex_enter(buf_pool);
 
3705
        buf_pool_mutex_enter();
4648
3706
 
4649
3707
        chunk = buf_pool->chunks;
4650
3708
 
4673
3731
                }
4674
3732
        }
4675
3733
 
4676
 
        mutex_enter(&buf_pool->zip_mutex);
 
3734
        mutex_enter(&buf_pool_zip_mutex);
4677
3735
 
4678
3736
        /* Traverse the lists of clean and dirty compressed-only blocks. */
4679
3737
 
4688
3746
                }
4689
3747
        }
4690
3748
 
4691
 
        buf_flush_list_mutex_enter(buf_pool);
4692
3749
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4693
3750
             b = UT_LIST_GET_NEXT(list, b)) {
4694
3751
                ut_ad(b->in_flush_list);
4714
3771
                }
4715
3772
        }
4716
3773
 
4717
 
        buf_flush_list_mutex_exit(buf_pool);
4718
 
        mutex_exit(&buf_pool->zip_mutex);
4719
 
        buf_pool_mutex_exit(buf_pool);
 
3774
        mutex_exit(&buf_pool_zip_mutex);
 
3775
        buf_pool_mutex_exit();
4720
3776
 
4721
3777
        return(fixed_pages_number);
4722
3778
}
4723
 
 
4724
 
/*********************************************************************//**
4725
 
Returns the number of latched pages in all the buffer pools.
4726
 
@return number of latched pages */
4727
 
UNIV_INTERN
4728
 
ulint
4729
 
buf_get_latched_pages_number(void)
4730
 
/*==============================*/
4731
 
{
4732
 
        ulint   i;
4733
 
        ulint   total_latched_pages = 0;
4734
 
 
4735
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4736
 
                buf_pool_t*     buf_pool;
4737
 
 
4738
 
                buf_pool = buf_pool_from_array(i);
4739
 
 
4740
 
                total_latched_pages += buf_get_latched_pages_number_instance(
4741
 
                        buf_pool);
4742
 
        }
4743
 
 
4744
 
        return(total_latched_pages);
4745
 
}
4746
 
 
4747
3779
#endif /* UNIV_DEBUG */
4748
3780
 
4749
3781
/*********************************************************************//**
4754
3786
buf_get_n_pending_ios(void)
4755
3787
/*=======================*/
4756
3788
{
4757
 
        ulint   i;
4758
 
        ulint   pend_ios = 0;
4759
 
 
4760
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4761
 
                buf_pool_t*     buf_pool;
4762
 
 
4763
 
                buf_pool = buf_pool_from_array(i);
4764
 
 
4765
 
                pend_ios +=
4766
 
                        buf_pool->n_pend_reads
4767
 
                        + buf_pool->n_flush[BUF_FLUSH_LRU]
4768
 
                        + buf_pool->n_flush[BUF_FLUSH_LIST]
4769
 
                        + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
4770
 
        }
4771
 
 
4772
 
        return(pend_ios);
 
3789
        return(buf_pool->n_pend_reads
 
3790
               + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3791
               + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3792
               + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4773
3793
}
4774
3794
 
4775
3795
/*********************************************************************//**
4781
3801
buf_get_modified_ratio_pct(void)
4782
3802
/*============================*/
4783
3803
{
4784
 
        ulint           ratio;
4785
 
        ulint           lru_len = 0;
4786
 
        ulint           free_len = 0;
4787
 
        ulint           flush_list_len = 0;
4788
 
 
4789
 
        buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
4790
 
 
4791
 
        ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
4792
 
  
 
3804
        ulint   ratio;
 
3805
 
 
3806
        buf_pool_mutex_enter();
 
3807
 
 
3808
        ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
 
3809
                / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
 
3810
                   + UT_LIST_GET_LEN(buf_pool->free));
 
3811
 
4793
3812
        /* 1 + is there to avoid division by zero */
4794
3813
 
 
3814
        buf_pool_mutex_exit();
 
3815
 
4795
3816
        return(ratio);
4796
3817
}
4797
3818
 
4798
3819
/*********************************************************************//**
4799
3820
Prints info of the buffer i/o. */
4800
 
static
 
3821
UNIV_INTERN
4801
3822
void
4802
 
buf_print_io_instance(
4803
 
/*==================*/
4804
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
4805
 
        FILE*           file)           /*!< in/out: buffer where to print */
 
3823
buf_print_io(
 
3824
/*=========*/
 
3825
        FILE*   file)   /*!< in/out: buffer where to print */
4806
3826
{
4807
3827
        time_t  current_time;
4808
3828
        double  time_elapsed;
4810
3830
 
4811
3831
        ut_ad(buf_pool);
4812
3832
 
4813
 
        buf_pool_mutex_enter(buf_pool);
4814
 
        buf_flush_list_mutex_enter(buf_pool);
 
3833
        buf_pool_mutex_enter();
4815
3834
 
4816
3835
        fprintf(file,
4817
3836
                "Buffer pool size   %lu\n"
4833
3852
                + buf_pool->init_flush[BUF_FLUSH_LIST],
4834
3853
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4835
3854
 
4836
 
        buf_flush_list_mutex_exit(buf_pool);
4837
 
 
4838
3855
        current_time = time(NULL);
4839
3856
        time_elapsed = 0.001 + difftime(current_time,
4840
3857
                                        buf_pool->last_printout_time);
4865
3882
                 - buf_pool->old_stat.n_pages_written)
4866
3883
                / time_elapsed);
4867
3884
 
4868
 
        n_gets_diff = buf_pool->stat.n_page_gets
4869
 
                    - buf_pool->old_stat.n_page_gets;
 
3885
        n_gets_diff = buf_pool->stat.n_page_gets - buf_pool->old_stat.n_page_gets;
4870
3886
 
4871
3887
        if (n_gets_diff) {
4872
3888
                fprintf(file,
4905
3921
        fprintf(file,
4906
3922
                "LRU len: %lu, unzip_LRU len: %lu\n"
4907
3923
                "I/O sum[%lu]:cur[%lu], unzip sum[%lu]:cur[%lu]\n",
4908
 
                static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->LRU)),
4909
 
                static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->unzip_LRU)),
 
3924
                UT_LIST_GET_LEN(buf_pool->LRU),
 
3925
                UT_LIST_GET_LEN(buf_pool->unzip_LRU),
4910
3926
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
4911
3927
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
4912
3928
 
4913
 
        buf_refresh_io_stats(buf_pool);
4914
 
        buf_pool_mutex_exit(buf_pool);
4915
 
}
4916
 
 
4917
 
/*********************************************************************//**
4918
 
Prints info of the buffer i/o. */
4919
 
UNIV_INTERN
4920
 
void
4921
 
buf_print_io(
4922
 
/*=========*/
4923
 
        FILE*   file)   /*!< in/out: buffer where to print */
4924
 
{
4925
 
        ulint   i;
4926
 
 
4927
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4928
 
                buf_pool_t*     buf_pool;
4929
 
 
4930
 
                buf_pool = buf_pool_from_array(i);
4931
 
                buf_print_io_instance(buf_pool, file);
4932
 
        }
 
3929
        buf_refresh_io_stats();
 
3930
        buf_pool_mutex_exit();
4933
3931
}
4934
3932
 
4935
3933
/**********************************************************************//**
4936
3934
Refreshes the statistics used to print per-second averages. */
4937
3935
UNIV_INTERN
4938
3936
void
4939
 
buf_refresh_io_stats(
4940
 
/*=================*/
4941
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3937
buf_refresh_io_stats(void)
 
3938
/*======================*/
4942
3939
{
4943
 
        buf_pool->last_printout_time = ut_time();
 
3940
        buf_pool->last_printout_time = time(NULL);
4944
3941
        buf_pool->old_stat = buf_pool->stat;
4945
3942
}
4946
3943
 
4947
 
/**********************************************************************//**
4948
 
Refreshes the statistics used to print per-second averages. */
4949
 
UNIV_INTERN
4950
 
void
4951
 
buf_refresh_io_stats_all(void)
4952
 
/*==========================*/
4953
 
{
4954
 
        ulint           i;
4955
 
 
4956
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4957
 
                buf_pool_t*     buf_pool;
4958
 
 
4959
 
                buf_pool = buf_pool_from_array(i);
4960
 
 
4961
 
                buf_refresh_io_stats(buf_pool);
4962
 
        }
4963
 
}
4964
 
 
4965
 
/**********************************************************************//**
4966
 
Check if all pages in all buffer pools are in a replacable state.
4967
 
@return FALSE if not */
 
3944
/*********************************************************************//**
 
3945
Asserts that all file pages in the buffer are in a replaceable state.
 
3946
@return TRUE */
4968
3947
UNIV_INTERN
4969
3948
ibool
4970
3949
buf_all_freed(void)
4971
3950
/*===============*/
4972
3951
{
4973
 
        ulint   i;
4974
 
 
4975
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4976
 
                buf_pool_t*     buf_pool;
4977
 
 
4978
 
                buf_pool = buf_pool_from_array(i);
4979
 
 
4980
 
                if (!buf_all_freed_instance(buf_pool)) {
4981
 
                        return(FALSE);
 
3952
        buf_chunk_t*    chunk;
 
3953
        ulint           i;
 
3954
 
 
3955
        ut_ad(buf_pool);
 
3956
 
 
3957
        buf_pool_mutex_enter();
 
3958
 
 
3959
        chunk = buf_pool->chunks;
 
3960
 
 
3961
        for (i = buf_pool->n_chunks; i--; chunk++) {
 
3962
 
 
3963
                const buf_block_t* block = buf_chunk_not_freed(chunk);
 
3964
 
 
3965
                if (UNIV_LIKELY_NULL(block)) {
 
3966
                        fprintf(stderr,
 
3967
                                "Page %lu %lu still fixed or dirty\n",
 
3968
                                (ulong) block->page.space,
 
3969
                                (ulong) block->page.offset);
 
3970
                        ut_error;
4982
3971
                }
4983
 
        }
 
3972
        }
 
3973
 
 
3974
        buf_pool_mutex_exit();
4984
3975
 
4985
3976
        return(TRUE);
4986
3977
}
4987
 
  
 
3978
 
4988
3979
/*********************************************************************//**
4989
3980
Checks that there currently are no pending i/o-operations for the buffer
4990
3981
pool.
4994
3985
buf_pool_check_no_pending_io(void)
4995
3986
/*==============================*/
4996
3987
{
4997
 
        ulint           i;
4998
 
        ibool           ret = TRUE;
4999
 
 
5000
 
        buf_pool_mutex_enter_all();
5001
 
 
5002
 
        for (i = 0; i < srv_buf_pool_instances && ret; i++) {
5003
 
                const buf_pool_t*       buf_pool;
5004
 
 
5005
 
                buf_pool = buf_pool_from_array(i);
5006
 
 
5007
 
                if (buf_pool->n_pend_reads
5008
 
                    + buf_pool->n_flush[BUF_FLUSH_LRU]
5009
 
                    + buf_pool->n_flush[BUF_FLUSH_LIST]
5010
 
                    + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
5011
 
 
5012
 
                        ret = FALSE;
5013
 
                }
 
3988
        ibool   ret;
 
3989
 
 
3990
        buf_pool_mutex_enter();
 
3991
 
 
3992
        if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3993
            + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3994
            + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
 
3995
                ret = FALSE;
 
3996
        } else {
 
3997
                ret = TRUE;
5014
3998
        }
5015
3999
 
5016
 
        buf_pool_mutex_exit_all();
 
4000
        buf_pool_mutex_exit();
5017
4001
 
5018
4002
        return(ret);
5019
4003
}
5020
4004
 
5021
 
#if 0
5022
 
Code currently not used
5023
4005
/*********************************************************************//**
5024
4006
Gets the current length of the free list of buffer blocks.
5025
4007
@return length of the free list */
5030
4012
{
5031
4013
        ulint   len;
5032
4014
 
5033
 
        buf_pool_mutex_enter(buf_pool);
 
4015
        buf_pool_mutex_enter();
5034
4016
 
5035
4017
        len = UT_LIST_GET_LEN(buf_pool->free);
5036
4018
 
5037
 
        buf_pool_mutex_exit(buf_pool);
 
4019
        buf_pool_mutex_exit();
5038
4020
 
5039
4021
        return(len);
5040
4022
}
5041
 
#endif
5042
 
 
5043
4023
#else /* !UNIV_HOTBACKUP */
5044
4024
/********************************************************************//**
5045
4025
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */