~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

Merge Stewart's dead code removal

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
18
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
19
 
20
20
You should have received a copy of the GNU General Public License along with
21
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
22
Place, Suite 330, Boston, MA 02111-1307 USA
23
23
 
24
24
*****************************************************************************/
25
25
 
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
 
#ifdef HAVE_VALGRIND
 
752
#ifdef HAVE_purify
978
753
                /* Wipe contents of frame to eliminate a Purify warning */
979
754
                memset(block->frame, '\0', UNIV_PAGE_SIZE);
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++) {
1068
 
                ibool   ready;
1069
 
 
1070
 
                switch (buf_block_get_state(block)) {
1071
 
                case BUF_BLOCK_ZIP_FREE:
1072
 
                case BUF_BLOCK_ZIP_PAGE:
1073
 
                case BUF_BLOCK_ZIP_DIRTY:
1074
 
                        /* The uncompressed buffer pool should never
1075
 
                        contain compressed block descriptors. */
1076
 
                        ut_error;
1077
 
                        break;
1078
 
                case BUF_BLOCK_NOT_USED:
1079
 
                case BUF_BLOCK_READY_FOR_USE:
1080
 
                case BUF_BLOCK_MEMORY:
1081
 
                case BUF_BLOCK_REMOVE_HASH:
1082
 
                        /* Skip blocks that are not being used for
1083
 
                        file pages. */
1084
 
                        break;
1085
 
                case BUF_BLOCK_FILE_PAGE:
1086
 
                        mutex_enter(&block->mutex);
1087
 
                        ready = buf_flush_ready_for_replace(&block->page);
 
840
                mutex_enter(&block->mutex);
 
841
 
 
842
                if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
 
843
                    && !buf_flush_ready_for_replace(&block->page)) {
 
844
 
1088
845
                        mutex_exit(&block->mutex);
1089
 
 
1090
 
                        if (!ready) {
1091
 
 
1092
 
                                return(block);
1093
 
                        }
1094
 
 
1095
 
                        break;
 
846
                        return(block);
1096
847
                }
 
848
 
 
849
                mutex_exit(&block->mutex);
1097
850
        }
1098
851
 
1099
852
        return(NULL);
1111
864
        const buf_block_t*      block;
1112
865
        ulint                   i;
1113
866
 
 
867
        ut_ad(buf_pool);
 
868
        ut_ad(buf_pool_mutex_own());
 
869
 
1114
870
        block = chunk->blocks;
1115
871
 
1116
872
        for (i = chunk->size; i--; block++) {
1130
886
void
1131
887
buf_chunk_free(
1132
888
/*===========*/
1133
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1134
889
        buf_chunk_t*    chunk)          /*!< out: chunk of buffers */
1135
890
{
1136
891
        buf_block_t*            block;
1137
892
        const buf_block_t*      block_end;
1138
893
 
1139
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
894
        ut_ad(buf_pool_mutex_own());
1140
895
 
1141
896
        block_end = chunk->blocks + chunk->size;
1142
897
 
1164
919
}
1165
920
 
1166
921
/********************************************************************//**
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
 
{
 
922
Creates the buffer pool.
 
923
@return own: buf_pool object, NULL if not enough memory or error */
 
924
UNIV_INTERN
 
925
buf_pool_t*
 
926
buf_pool_init(void)
 
927
/*===============*/
 
928
{
 
929
        buf_chunk_t*    chunk;
1202
930
        ulint           i;
1203
 
        buf_chunk_t*    chunk;
 
931
 
 
932
        buf_pool = mem_zalloc(sizeof(buf_pool_t));
1204
933
 
1205
934
        /* 1. Initialize general fields
1206
935
        ------------------------------- */
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();
 
936
        mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
 
937
        mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
 
938
 
 
939
        buf_pool_mutex_enter();
 
940
 
 
941
        buf_pool->n_chunks = 1;
 
942
        buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
 
943
 
 
944
        UT_LIST_INIT(buf_pool->free);
 
945
 
 
946
        if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
 
947
                mem_free(chunk);
 
948
                mem_free(buf_pool);
 
949
                buf_pool = NULL;
 
950
                return(NULL);
1239
951
        }
 
952
 
 
953
        srv_buf_pool_old_size = srv_buf_pool_size;
 
954
        buf_pool->curr_size = chunk->size;
 
955
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
956
 
 
957
        buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
 
958
        buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
 
959
 
 
960
        buf_pool->last_printout_time = time(NULL);
 
961
 
1240
962
        /* 2. Initialize flushing fields
1241
963
        -------------------------------- */
1242
964
 
1243
 
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1244
 
                     SYNC_BUF_FLUSH_LIST);
1245
 
 
1246
965
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
1247
966
                buf_pool->no_flush[i] = os_event_create(NULL);
1248
967
        }
1249
968
 
 
969
        buf_pool->ulint_clock = 1;
 
970
 
1250
971
        /* 3. Initialize LRU fields
1251
972
        --------------------------- */
1252
 
 
1253
 
        /* All fields are initialized by mem_zalloc(). */
1254
 
 
1255
 
        buf_pool_mutex_exit(buf_pool);
1256
 
 
1257
 
        return(DB_SUCCESS);
 
973
        /* All fields are initialized by mem_zalloc(). */
 
974
 
 
975
        buf_pool_mutex_exit();
 
976
 
 
977
        btr_search_sys_create(buf_pool->curr_size
 
978
                              * UNIV_PAGE_SIZE / sizeof(void*) / 64);
 
979
 
 
980
        /* 4. Initialize the buddy allocator fields */
 
981
        /* All fields are initialized by mem_zalloc(). */
 
982
 
 
983
        return(buf_pool);
1258
984
}
1259
985
 
1260
986
/********************************************************************//**
1261
 
free one buffer pool instance */
1262
 
static
 
987
Frees the buffer pool at shutdown.  This must not be invoked before
 
988
freeing all mutexes. */
 
989
UNIV_INTERN
1263
990
void
1264
 
buf_pool_free_instance(
1265
 
/*===================*/
1266
 
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
1267
 
                                        to free */
 
991
buf_pool_free(void)
 
992
/*===============*/
1268
993
{
1269
994
        buf_chunk_t*    chunk;
1270
995
        buf_chunk_t*    chunks;
1278
1003
                os_mem_free_large(chunk->mem, chunk->mem_size);
1279
1004
        }
1280
1005
 
1281
 
        mem_free(buf_pool->chunks);
1282
 
        hash_table_free(buf_pool->page_hash);
1283
 
        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
 
 
 
1006
        buf_pool->n_chunks = 0;
 
1007
}
 
1008
 
1420
1009
/********************************************************************//**
1421
1010
Drops the adaptive hash index.  To prevent a livelock, this function
1422
1011
is only to be called while holding btr_search_latch and while
1434
1023
        ut_ad(!btr_search_enabled);
1435
1024
 
1436
1025
        do {
1437
 
                ulint   i;
 
1026
                buf_chunk_t*    chunks  = buf_pool->chunks;
 
1027
                buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
1438
1028
 
1439
1029
                released_search_latch = FALSE;
1440
1030
 
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);
 
1031
                while (--chunk >= chunks) {
 
1032
                        buf_block_t*    block   = chunk->blocks;
 
1033
                        ulint           i       = chunk->size;
 
1034
 
 
1035
                        for (; i--; block++) {
 
1036
                                /* block->is_hashed cannot be modified
 
1037
                                when we have an x-latch on btr_search_latch;
 
1038
                                see the comment in buf0buf.h */
 
1039
 
 
1040
                                if (!block->is_hashed) {
 
1041
                                        continue;
 
1042
                                }
 
1043
 
 
1044
                                /* To follow the latching order, we
 
1045
                                have to release btr_search_latch
 
1046
                                before acquiring block->latch. */
 
1047
                                rw_lock_x_unlock(&btr_search_latch);
 
1048
                                /* When we release the search latch,
 
1049
                                we must rescan all blocks, because
 
1050
                                some may become hashed again. */
 
1051
                                released_search_latch = TRUE;
 
1052
 
 
1053
                                rw_lock_x_lock(&block->lock);
 
1054
 
 
1055
                                /* This should be guaranteed by the
 
1056
                                callers, which will be holding
 
1057
                                btr_search_enabled_mutex. */
 
1058
                                ut_ad(!btr_search_enabled);
 
1059
 
 
1060
                                /* Because we did not buffer-fix the
 
1061
                                block by calling buf_block_get_gen(),
 
1062
                                it is possible that the block has been
 
1063
                                allocated for some other use after
 
1064
                                btr_search_latch was released above.
 
1065
                                We do not care which file page the
 
1066
                                block is mapped to.  All we want to do
 
1067
                                is to drop any hash entries referring
 
1068
                                to the page. */
 
1069
 
 
1070
                                /* It is possible that
 
1071
                                block->page.state != BUF_FILE_PAGE.
 
1072
                                Even that does not matter, because
 
1073
                                btr_search_drop_page_hash_index() will
 
1074
                                check block->is_hashed before doing
 
1075
                                anything.  block->is_hashed can only
 
1076
                                be set on uncompressed file pages. */
 
1077
 
 
1078
                                btr_search_drop_page_hash_index(block);
 
1079
 
 
1080
                                rw_lock_x_unlock(&block->lock);
 
1081
 
 
1082
                                rw_lock_x_lock(&btr_search_latch);
 
1083
 
 
1084
                                ut_ad(!btr_search_enabled);
 
1085
                        }
1448
1086
                }
1449
 
 
1450
1087
        } while (released_search_latch);
1451
1088
}
1452
1089
 
1465
1102
{
1466
1103
        buf_page_t*     b;
1467
1104
        ulint           fold;
1468
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1469
1105
 
1470
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1106
        ut_ad(buf_pool_mutex_own());
1471
1107
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1472
1108
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1473
1109
        ut_a(bpage->buf_fix_count == 0);
1474
1110
        ut_ad(bpage->in_LRU_list);
1475
1111
        ut_ad(!bpage->in_zip_hash);
1476
1112
        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));
 
1113
        ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
1480
1114
#ifdef UNIV_DEBUG
1481
1115
        switch (buf_page_get_state(bpage)) {
1482
1116
        case BUF_BLOCK_ZIP_FREE:
1512
1146
#ifdef UNIV_LRU_DEBUG
1513
1147
                /* buf_pool->LRU_old must be the first item in the LRU list
1514
1148
                whose "old" flag is set. */
1515
 
                ut_a(buf_pool->LRU_old->old);
1516
1149
                ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
1517
1150
                     || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
1518
1151
                ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
1519
1152
                     || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
1520
 
        } else {
1521
 
                /* Check that the "old" flag is consistent in
1522
 
                the block and its neighbours. */
1523
 
                buf_page_set_old(dpage, buf_page_is_old(dpage));
1524
1153
#endif /* UNIV_LRU_DEBUG */
1525
1154
        }
1526
1155
 
1532
1161
 
1533
1162
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
1534
1163
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
 
1164
 
 
1165
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
1535
1166
}
1536
1167
 
1537
1168
/********************************************************************//**
1538
 
Shrinks a buffer pool instance. */
 
1169
Shrinks the buffer pool. */
1539
1170
static
1540
1171
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 */
 
1172
buf_pool_shrink(
 
1173
/*============*/
 
1174
        ulint   chunk_size)     /*!< in: number of pages to remove */
1545
1175
{
1546
1176
        buf_chunk_t*    chunks;
1547
1177
        buf_chunk_t*    chunk;
1550
1180
        buf_chunk_t*    max_chunk;
1551
1181
        buf_chunk_t*    max_free_chunk;
1552
1182
 
1553
 
        ut_ad(!buf_pool_mutex_own(buf_pool));
 
1183
        ut_ad(!buf_pool_mutex_own());
1554
1184
 
1555
1185
try_again:
1556
1186
        btr_search_disable(); /* Empty the adaptive hash index again */
1557
 
        buf_pool_mutex_enter(buf_pool);
 
1187
        buf_pool_mutex_enter();
1558
1188
 
1559
1189
shrink_again:
1560
1190
        if (buf_pool->n_chunks <= 1) {
1617
1247
 
1618
1248
                        mutex_enter(&block->mutex);
1619
1249
                        /* The following calls will temporarily
1620
 
                        release block->mutex and buf_pool->mutex.
 
1250
                        release block->mutex and buf_pool_mutex.
1621
1251
                        Therefore, we have to always retry,
1622
1252
                        even if !dirty && !nonfree. */
1623
1253
 
1633
1263
                        mutex_exit(&block->mutex);
1634
1264
                }
1635
1265
 
1636
 
                buf_pool_mutex_exit(buf_pool);
 
1266
                buf_pool_mutex_exit();
1637
1267
 
1638
1268
                /* Request for a flush of the chunk if it helps.
1639
1269
                Do not flush if there are non-free blocks, since
1642
1272
                        /* Avoid busy-waiting. */
1643
1273
                        os_thread_sleep(100000);
1644
1274
                } else if (dirty
1645
 
                           && buf_flush_LRU(buf_pool, dirty)
1646
 
                              == ULINT_UNDEFINED) {
 
1275
                           && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
 
1276
                           == ULINT_UNDEFINED) {
1647
1277
 
1648
 
                        buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
 
1278
                        buf_flush_wait_batch_end(BUF_FLUSH_LRU);
1649
1279
                }
1650
1280
 
1651
1281
                goto try_again;
1654
1284
        max_size = max_free_size;
1655
1285
        max_chunk = max_free_chunk;
1656
1286
 
1657
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1287
        srv_buf_pool_old_size = srv_buf_pool_size;
1658
1288
 
1659
1289
        /* 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));
 
1290
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
1661
1291
        memcpy(chunks, buf_pool->chunks,
1662
1292
               (max_chunk - buf_pool->chunks) * sizeof *chunks);
1663
1293
        memcpy(chunks + (max_chunk - buf_pool->chunks),
1666
1296
               - (max_chunk + 1));
1667
1297
        ut_a(buf_pool->curr_size > max_chunk->size);
1668
1298
        buf_pool->curr_size -= max_chunk->size;
1669
 
        buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1299
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1670
1300
        chunk_size -= max_chunk->size;
1671
 
        buf_chunk_free(buf_pool, max_chunk);
 
1301
        buf_chunk_free(max_chunk);
1672
1302
        mem_free(buf_pool->chunks);
1673
1303
        buf_pool->chunks = chunks;
1674
1304
        buf_pool->n_chunks--;
1678
1308
 
1679
1309
                goto shrink_again;
1680
1310
        }
1681
 
        goto func_exit;
1682
1311
 
1683
1312
func_done:
1684
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1313
        srv_buf_pool_old_size = srv_buf_pool_size;
1685
1314
func_exit:
1686
 
        buf_pool_mutex_exit(buf_pool);
 
1315
        buf_pool_mutex_exit();
1687
1316
        btr_search_enable();
1688
1317
}
1689
1318
 
1690
1319
/********************************************************************//**
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 */
 
1320
Rebuild buf_pool->page_hash. */
 
1321
static
 
1322
void
 
1323
buf_pool_page_hash_rebuild(void)
 
1324
/*============================*/
1719
1325
{
1720
1326
        ulint           i;
1721
 
        buf_page_t*     b;
1722
 
        buf_chunk_t*    chunk;
1723
1327
        ulint           n_chunks;
 
1328
        buf_chunk_t*    chunk;
 
1329
        hash_table_t*   page_hash;
1724
1330
        hash_table_t*   zip_hash;
1725
 
        hash_table_t*   page_hash;
 
1331
        buf_page_t*     b;
1726
1332
 
1727
 
        buf_pool_mutex_enter(buf_pool);
 
1333
        buf_pool_mutex_enter();
1728
1334
 
1729
1335
        /* Free, create, and populate the hash table. */
1730
1336
        hash_table_free(buf_pool->page_hash);
1777
1383
                            buf_page_address_fold(b->space, b->offset), b);
1778
1384
        }
1779
1385
 
1780
 
        buf_flush_list_mutex_enter(buf_pool);
1781
1386
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1782
1387
             b = UT_LIST_GET_NEXT(list, b)) {
1783
1388
                ut_ad(b->in_flush_list);
1805
1410
                }
1806
1411
        }
1807
1412
 
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();
 
1413
        buf_pool_mutex_exit();
1982
1414
}
1983
1415
 
1984
1416
/********************************************************************//**
1988
1420
buf_pool_resize(void)
1989
1421
/*=================*/
1990
1422
{
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
 
 
 
1423
        buf_pool_mutex_enter();
 
1424
 
 
1425
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
 
1426
 
 
1427
                buf_pool_mutex_exit();
2029
1428
                return;
2030
1429
        }
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(
 
1430
 
 
1431
        if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
 
1432
 
 
1433
                buf_pool_mutex_exit();
 
1434
 
 
1435
                /* Disable adaptive hash indexes and empty the index
 
1436
                in order to free up memory in the buffer pool chunks. */
 
1437
                buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
 
1438
                                / UNIV_PAGE_SIZE);
 
1439
        } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
 
1440
 
 
1441
                /* Enlarge the buffer pool by at least one megabyte */
 
1442
 
 
1443
                ulint           mem_size
 
1444
                        = srv_buf_pool_size - srv_buf_pool_curr_size;
 
1445
                buf_chunk_t*    chunks;
 
1446
                buf_chunk_t*    chunk;
 
1447
 
 
1448
                chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
 
1449
 
 
1450
                memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
 
1451
                       * sizeof *chunks);
 
1452
 
 
1453
                chunk = &chunks[buf_pool->n_chunks];
 
1454
 
 
1455
                if (!buf_chunk_init(chunk, mem_size)) {
 
1456
                        mem_free(chunks);
 
1457
                } else {
 
1458
                        buf_pool->curr_size += chunk->size;
 
1459
                        srv_buf_pool_curr_size = buf_pool->curr_size
 
1460
                                * UNIV_PAGE_SIZE;
 
1461
                        mem_free(buf_pool->chunks);
 
1462
                        buf_pool->chunks = chunks;
 
1463
                        buf_pool->n_chunks++;
 
1464
                }
 
1465
 
 
1466
                srv_buf_pool_old_size = srv_buf_pool_size;
 
1467
                buf_pool_mutex_exit();
 
1468
        }
 
1469
 
 
1470
        buf_pool_page_hash_rebuild();
 
1471
}
 
1472
 
 
1473
/********************************************************************//**
 
1474
Moves the block to the start of the LRU list if there is a danger
 
1475
that the block would drift out of the buffer pool. */
 
1476
UNIV_INLINE
 
1477
void
 
1478
buf_block_make_young(
2063
1479
/*=================*/
2064
 
        ulint   space,  /*!< in: space id */
2065
 
        ulint   offset) /*!< in: page number */
 
1480
        buf_page_t*     bpage)  /*!< in: block to make younger */
2066
1481
{
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);
2089
 
                }
 
1482
        ut_ad(!buf_pool_mutex_own());
 
1483
 
 
1484
        /* Note that we read freed_page_clock's without holding any mutex:
 
1485
        this is allowed since the result is used only in heuristics */
 
1486
 
 
1487
        if (buf_page_peek_if_too_old(bpage)) {
 
1488
 
 
1489
                buf_pool_mutex_enter();
 
1490
                /* There has been freeing activity in the LRU list:
 
1491
                best to move to the head of the LRU list */
 
1492
 
 
1493
                buf_LRU_make_block_young(bpage);
 
1494
                buf_pool_mutex_exit();
2090
1495
        }
2091
 
 
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);
2122
1496
}
2123
1497
 
2124
1498
/********************************************************************//**
2125
1499
Moves a page to the start of the buffer pool LRU list. This high-level
2126
 
function can be used to prevent an important page from slipping out of
 
1500
function can be used to prevent an important page from from slipping out of
2127
1501
the buffer pool. */
2128
1502
UNIV_INTERN
2129
1503
void
2131
1505
/*================*/
2132
1506
        buf_page_t*     bpage)  /*!< in: buffer block of a file page */
2133
1507
{
2134
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2135
 
 
2136
 
        buf_pool_mutex_enter(buf_pool);
 
1508
        buf_pool_mutex_enter();
2137
1509
 
2138
1510
        ut_a(buf_page_in_file(bpage));
2139
1511
 
2140
1512
        buf_LRU_make_block_young(bpage);
2141
1513
 
2142
 
        buf_pool_mutex_exit(buf_pool);
2143
 
}
2144
 
 
2145
 
/********************************************************************//**
2146
 
Sets the time of the first access of a page and moves a page to the
2147
 
start of the buffer pool LRU list if it is too old.  This high-level
2148
 
function can be used to prevent an important page from slipping
2149
 
out of the buffer pool. */
2150
 
static
2151
 
void
2152
 
buf_page_set_accessed_make_young(
2153
 
/*=============================*/
2154
 
        buf_page_t*     bpage,          /*!< in/out: buffer block of a
2155
 
                                        file page */
2156
 
        unsigned        access_time)    /*!< in: bpage->access_time
2157
 
                                        read under mutex protection,
2158
 
                                        or 0 if unknown */
2159
 
{
2160
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2161
 
 
2162
 
        ut_ad(!buf_pool_mutex_own(buf_pool));
2163
 
        ut_a(buf_page_in_file(bpage));
2164
 
 
2165
 
        if (buf_page_peek_if_too_old(bpage)) {
2166
 
                buf_pool_mutex_enter(buf_pool);
2167
 
                buf_LRU_make_block_young(bpage);
2168
 
                buf_pool_mutex_exit(buf_pool);
2169
 
        } else if (!access_time) {
2170
 
                ulint   time_ms = ut_time_ms();
2171
 
                buf_pool_mutex_enter(buf_pool);
2172
 
                buf_page_set_accessed(bpage, time_ms);
2173
 
                buf_pool_mutex_exit(buf_pool);
2174
 
        }
 
1514
        buf_pool_mutex_exit();
2175
1515
}
2176
1516
 
2177
1517
/********************************************************************//**
2185
1525
        ulint   offset) /*!< in: page number */
2186
1526
{
2187
1527
        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);
 
1528
 
 
1529
        buf_pool_mutex_enter();
 
1530
 
 
1531
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2193
1532
 
2194
1533
        if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
2195
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2196
1534
                block->check_index_page_at_flush = FALSE;
2197
1535
        }
2198
1536
 
2199
 
        buf_pool_mutex_exit(buf_pool);
 
1537
        buf_pool_mutex_exit();
2200
1538
}
2201
1539
 
2202
1540
/********************************************************************//**
2213
1551
{
2214
1552
        buf_block_t*    block;
2215
1553
        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);
 
1554
 
 
1555
        buf_pool_mutex_enter();
 
1556
 
 
1557
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2221
1558
 
2222
1559
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2223
1560
                is_hashed = FALSE;
2224
1561
        } else {
2225
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2226
1562
                is_hashed = block->is_hashed;
2227
1563
        }
2228
1564
 
2229
 
        buf_pool_mutex_exit(buf_pool);
 
1565
        buf_pool_mutex_exit();
2230
1566
 
2231
1567
        return(is_hashed);
2232
1568
}
2246
1582
        ulint   offset) /*!< in: page number */
2247
1583
{
2248
1584
        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);
 
1585
 
 
1586
        buf_pool_mutex_enter();
 
1587
 
 
1588
        bpage = buf_page_hash_get(space, offset);
2254
1589
 
2255
1590
        if (bpage) {
2256
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2257
1591
                bpage->file_page_was_freed = TRUE;
2258
1592
        }
2259
1593
 
2260
 
        buf_pool_mutex_exit(buf_pool);
 
1594
        buf_pool_mutex_exit();
2261
1595
 
2262
1596
        return(bpage);
2263
1597
}
2276
1610
        ulint   offset) /*!< in: page number */
2277
1611
{
2278
1612
        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);
 
1613
 
 
1614
        buf_pool_mutex_enter();
 
1615
 
 
1616
        bpage = buf_page_hash_get(space, offset);
2284
1617
 
2285
1618
        if (bpage) {
2286
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2287
1619
                bpage->file_page_was_freed = FALSE;
2288
1620
        }
2289
1621
 
2290
 
        buf_pool_mutex_exit(buf_pool);
 
1622
        buf_pool_mutex_exit();
2291
1623
 
2292
1624
        return(bpage);
2293
1625
}
2313
1645
        buf_page_t*     bpage;
2314
1646
        mutex_t*        block_mutex;
2315
1647
        ibool           must_read;
2316
 
        unsigned        access_time;
2317
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2318
1648
 
2319
1649
#ifndef UNIV_LOG_DEBUG
2320
1650
        ut_ad(!ibuf_inside());
2321
1651
#endif
2322
 
        buf_pool->stat.n_page_gets++;
 
1652
        buf_pool->n_page_gets++;
2323
1653
 
2324
1654
        for (;;) {
2325
 
                buf_pool_mutex_enter(buf_pool);
 
1655
                buf_pool_mutex_enter();
2326
1656
lookup:
2327
 
                bpage = buf_page_hash_get(buf_pool, space, offset);
 
1657
                bpage = buf_page_hash_get(space, offset);
2328
1658
                if (bpage) {
2329
 
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2330
1659
                        break;
2331
1660
                }
2332
1661
 
2333
1662
                /* Page not in buf_pool: needs to be read from file */
2334
1663
 
2335
 
                buf_pool_mutex_exit(buf_pool);
 
1664
                buf_pool_mutex_exit();
2336
1665
 
2337
1666
                buf_read_page(space, zip_size, offset);
2338
1667
 
2344
1673
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
2345
1674
                /* There is no compressed page. */
2346
1675
err_exit:
2347
 
                buf_pool_mutex_exit(buf_pool);
 
1676
                buf_pool_mutex_exit();
2348
1677
                return(NULL);
2349
1678
        }
2350
1679
 
2351
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2352
 
 
2353
1680
        switch (buf_page_get_state(bpage)) {
2354
1681
        case BUF_BLOCK_NOT_USED:
2355
1682
        case BUF_BLOCK_READY_FOR_USE:
2359
1686
                break;
2360
1687
        case BUF_BLOCK_ZIP_PAGE:
2361
1688
        case BUF_BLOCK_ZIP_DIRTY:
2362
 
                block_mutex = &buf_pool->zip_mutex;
 
1689
                block_mutex = &buf_pool_zip_mutex;
2363
1690
                mutex_enter(block_mutex);
2364
1691
                bpage->buf_fix_count++;
2365
1692
                goto got_block;
2385
1712
 
2386
1713
got_block:
2387
1714
        must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
2388
 
        access_time = buf_page_is_accessed(bpage);
2389
 
 
2390
 
        buf_pool_mutex_exit(buf_pool);
 
1715
 
 
1716
        buf_pool_mutex_exit();
 
1717
 
 
1718
        buf_page_set_accessed(bpage, TRUE);
2391
1719
 
2392
1720
        mutex_exit(block_mutex);
2393
1721
 
2394
 
        buf_page_set_accessed_make_young(bpage, access_time);
 
1722
        buf_block_make_young(bpage);
2395
1723
 
2396
1724
#ifdef UNIV_DEBUG_FILE_ACCESSES
2397
1725
        ut_a(!bpage->file_page_was_freed);
2459
1787
        buf_block_t*    block,  /*!< in/out: block */
2460
1788
        ibool           check)  /*!< in: TRUE=verify the page checksum */
2461
1789
{
2462
 
        const byte*     frame           = block->page.zip.data;
2463
 
        ulint           stamp_checksum  = mach_read_from_4(
2464
 
                frame + FIL_PAGE_SPACE_OR_CHKSUM);
 
1790
        const byte* frame = block->page.zip.data;
2465
1791
 
2466
1792
        ut_ad(buf_block_get_zip_size(block));
2467
1793
        ut_a(buf_block_get_space(block) != 0);
2468
1794
 
2469
 
        if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
 
1795
        if (UNIV_LIKELY(check)) {
 
1796
                ulint   stamp_checksum  = mach_read_from_4(
 
1797
                        frame + FIL_PAGE_SPACE_OR_CHKSUM);
2470
1798
                ulint   calc_checksum   = page_zip_calc_checksum(
2471
1799
                        frame, page_zip_get_size(&block->page.zip));
2472
1800
 
2484
1812
        switch (fil_page_get_type(frame)) {
2485
1813
        case FIL_PAGE_INDEX:
2486
1814
                if (page_zip_decompress(&block->page.zip,
2487
 
                                        block->frame, TRUE)) {
 
1815
                                        block->frame)) {
2488
1816
                        return(TRUE);
2489
1817
                }
2490
1818
 
2517
1845
 
2518
1846
#ifndef UNIV_HOTBACKUP
2519
1847
/*******************************************************************//**
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
 
1848
Gets the block to whose frame the pointer is pointing to.
 
1849
@return pointer to block, never NULL */
 
1850
UNIV_INTERN
2524
1851
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 */
 
1852
buf_block_align(
 
1853
/*============*/
 
1854
        const byte*     ptr)    /*!< in: pointer to a frame */
2530
1855
{
2531
1856
        buf_chunk_t*    chunk;
2532
1857
        ulint           i;
2552
1877
                        ut_ad(block->frame == page_align(ptr));
2553
1878
#ifdef UNIV_DEBUG
2554
1879
                        /* A thread that updates these fields must
2555
 
                        hold buf_pool->mutex and block->mutex.  Acquire
 
1880
                        hold buf_pool_mutex and block->mutex.  Acquire
2556
1881
                        only the latter. */
2557
1882
                        mutex_enter(&block->mutex);
2558
1883
 
2601
1926
                }
2602
1927
        }
2603
1928
 
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
1929
        /* The block should always be found. */
2629
1930
        ut_error;
2630
1931
        return(NULL);
2632
1933
 
2633
1934
/********************************************************************//**
2634
1935
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.
 
1936
the buf_block_t itself or a member of it
2637
1937
@return TRUE if ptr belongs to a buf_block_t struct */
2638
 
static
 
1938
UNIV_INTERN
2639
1939
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 */
 
1940
buf_pointer_is_block_field(
 
1941
/*=======================*/
 
1942
        const void*             ptr)    /*!< in: pointer not
 
1943
                                        dereferenced */
2644
1944
{
2645
1945
        const buf_chunk_t*              chunk   = buf_pool->chunks;
2646
1946
        const buf_chunk_t* const        echunk  = chunk + buf_pool->n_chunks;
2661
1961
}
2662
1962
 
2663
1963
/********************************************************************//**
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
1964
Find out if a buffer block was created by buf_chunk_init().
2690
1965
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
2691
1966
static
2692
1967
ibool
2693
1968
buf_block_is_uncompressed(
2694
1969
/*======================*/
2695
 
        buf_pool_t*             buf_pool,       /*!< in: buffer pool instance */
2696
 
        const buf_block_t*      block)          /*!< in: pointer to block,
2697
 
                                                not dereferenced */
 
1970
        const buf_block_t*      block)  /*!< in: pointer to block,
 
1971
                                        not dereferenced */
2698
1972
{
2699
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1973
        ut_ad(buf_pool_mutex_own());
2700
1974
 
2701
1975
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2702
1976
                /* The pointer should be aligned. */
2703
1977
                return(FALSE);
2704
1978
        }
2705
1979
 
2706
 
        return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
 
1980
        return(buf_pointer_is_block_field((void *)block));
2707
1981
}
2708
1982
 
2709
1983
/********************************************************************//**
2720
1994
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2721
1995
        buf_block_t*    guess,  /*!< in: guessed block or NULL */
2722
1996
        ulint           mode,   /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2723
 
                                BUF_GET_NO_LATCH, or
2724
 
                                BUF_GET_IF_IN_POOL_OR_WATCH */
 
1997
                                BUF_GET_NO_LATCH */
2725
1998
        const char*     file,   /*!< in: file name */
2726
1999
        ulint           line,   /*!< in: line where called */
2727
2000
        mtr_t*          mtr)    /*!< in: mini-transaction */
2728
2001
{
2729
2002
        buf_block_t*    block;
2730
 
        ulint           fold;
2731
 
        unsigned        access_time;
 
2003
        ibool           accessed;
2732
2004
        ulint           fix_type;
2733
2005
        ibool           must_read;
2734
 
        ulint           retries = 0;
2735
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2736
2006
 
2737
2007
        ut_ad(mtr);
2738
 
        ut_ad(mtr->state == MTR_ACTIVE);
2739
2008
        ut_ad((rw_latch == RW_S_LATCH)
2740
2009
              || (rw_latch == RW_X_LATCH)
2741
2010
              || (rw_latch == RW_NO_LATCH));
2742
2011
        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);
 
2012
        ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
 
2013
              || (mode == BUF_GET_NO_LATCH));
2747
2014
        ut_ad(zip_size == fil_space_get_zip_size(space));
2748
2015
        ut_ad(ut_is_2pow(zip_size));
2749
2016
#ifndef UNIV_LOG_DEBUG
2750
2017
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2751
2018
#endif
2752
 
        buf_pool->stat.n_page_gets++;
2753
 
        fold = buf_page_address_fold(space, offset);
 
2019
        buf_pool->n_page_gets++;
2754
2020
loop:
2755
2021
        block = guess;
2756
 
        buf_pool_mutex_enter(buf_pool);
 
2022
        buf_pool_mutex_enter();
2757
2023
 
2758
2024
        if (block) {
2759
2025
                /* If the guess is a compressed page descriptor that
2764
2030
                the guess may be pointing to a buffer pool chunk that
2765
2031
                has been released when resizing the buffer pool. */
2766
2032
 
2767
 
                if (!buf_block_is_uncompressed(buf_pool, block)
 
2033
                if (!buf_block_is_uncompressed(block)
2768
2034
                    || offset != block->page.offset
2769
2035
                    || space != block->page.space
2770
2036
                    || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2777
2043
        }
2778
2044
 
2779
2045
        if (block == NULL) {
2780
 
                block = (buf_block_t*) buf_page_hash_get_low(
2781
 
                        buf_pool, space, offset, fold);
 
2046
                block = (buf_block_t*) buf_page_hash_get(space, offset);
2782
2047
        }
2783
2048
 
2784
2049
loop2:
2785
 
        if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2786
 
                block = NULL;
2787
 
        }
2788
 
 
2789
2050
        if (block == NULL) {
2790
2051
                /* Page not in buf_pool: needs to be read from file */
2791
2052
 
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) {
 
2053
                buf_pool_mutex_exit();
 
2054
 
 
2055
                if (mode == BUF_GET_IF_IN_POOL) {
2806
2056
 
2807
2057
                        return(NULL);
2808
2058
                }
2809
2059
 
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
 
                }
 
2060
                buf_read_page(space, zip_size, offset);
2833
2061
 
2834
2062
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2835
2063
                ut_a(++buf_dbg_counter % 37 || buf_validate());
2837
2065
                goto loop;
2838
2066
        }
2839
2067
 
2840
 
got_block:
2841
2068
        ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
2842
2069
 
2843
2070
        must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
2844
2071
 
2845
2072
        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);
 
2073
                /* The page is only being read to buffer */
 
2074
                buf_pool_mutex_exit();
2851
2075
 
2852
2076
                return(NULL);
2853
2077
        }
2863
2087
        case BUF_BLOCK_ZIP_DIRTY:
2864
2088
                bpage = &block->page;
2865
2089
                /* Protect bpage->buf_fix_count. */
2866
 
                mutex_enter(&buf_pool->zip_mutex);
 
2090
                mutex_enter(&buf_pool_zip_mutex);
2867
2091
 
2868
2092
                if (bpage->buf_fix_count
2869
2093
                    || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2870
2094
                        /* This condition often occurs when the buffer
2871
2095
                        is not buffer-fixed, but I/O-fixed by
2872
2096
                        buf_page_init_for_read(). */
2873
 
                        mutex_exit(&buf_pool->zip_mutex);
 
2097
                        mutex_exit(&buf_pool_zip_mutex);
2874
2098
wait_until_unfixed:
2875
2099
                        /* The block is buffer-fixed or I/O-fixed.
2876
2100
                        Try again later. */
2877
 
                        buf_pool_mutex_exit(buf_pool);
 
2101
                        buf_pool_mutex_exit();
2878
2102
                        os_thread_sleep(WAIT_FOR_READ);
2879
 
  
 
2103
 
2880
2104
                        goto loop;
2881
2105
                }
2882
2106
 
2883
2107
                /* Allocate an uncompressed page. */
2884
 
                buf_pool_mutex_exit(buf_pool);
2885
 
                mutex_exit(&buf_pool->zip_mutex);
 
2108
                buf_pool_mutex_exit();
 
2109
                mutex_exit(&buf_pool_zip_mutex);
2886
2110
 
2887
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2111
                block = buf_LRU_get_free_block(0);
2888
2112
                ut_a(block);
2889
2113
 
2890
 
                buf_pool_mutex_enter(buf_pool);
 
2114
                buf_pool_mutex_enter();
2891
2115
                mutex_enter(&block->mutex);
2892
2116
 
2893
2117
                {
2894
 
                        buf_page_t*     hash_bpage;
2895
 
 
2896
 
                        hash_bpage = buf_page_hash_get_low(
2897
 
                                buf_pool, space, offset, fold);
 
2118
                        buf_page_t*     hash_bpage
 
2119
                                = buf_page_hash_get(space, offset);
2898
2120
 
2899
2121
                        if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2900
2122
                                /* The buf_pool->page_hash was modified
2901
 
                                while buf_pool->mutex was released.
 
2123
                                while buf_pool_mutex was released.
2902
2124
                                Free the block that was allocated. */
2903
2125
 
2904
2126
                                buf_LRU_block_free_non_file_page(block);
2914
2136
                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
2915
2137
 
2916
2138
                        /* The block was buffer-fixed or I/O-fixed
2917
 
                        while buf_pool->mutex was not held by this thread.
 
2139
                        while buf_pool_mutex was not held by this thread.
2918
2140
                        Free the block that was allocated and try again.
2919
2141
                        This should be extremely unlikely. */
2920
2142
 
2927
2149
                /* Move the compressed page from bpage to block,
2928
2150
                and uncompress it. */
2929
2151
 
2930
 
                mutex_enter(&buf_pool->zip_mutex);
 
2152
                mutex_enter(&buf_pool_zip_mutex);
2931
2153
 
2932
2154
                buf_relocate(bpage, &block->page);
2933
2155
                buf_block_init_low(block);
2943
2165
                        ut_ad(!block->page.in_flush_list);
2944
2166
                } else {
2945
2167
                        /* Relocate buf_pool->flush_list. */
2946
 
                        buf_flush_relocate_on_flush_list(bpage,
2947
 
                                                         &block->page);
 
2168
                        buf_page_t*     b;
 
2169
 
 
2170
                        b = UT_LIST_GET_PREV(list, &block->page);
 
2171
                        ut_ad(block->page.in_flush_list);
 
2172
                        UT_LIST_REMOVE(list, buf_pool->flush_list,
 
2173
                                       &block->page);
 
2174
 
 
2175
                        if (b) {
 
2176
                                UT_LIST_INSERT_AFTER(
 
2177
                                        list, buf_pool->flush_list, b,
 
2178
                                        &block->page);
 
2179
                        } else {
 
2180
                                UT_LIST_ADD_FIRST(
 
2181
                                        list, buf_pool->flush_list,
 
2182
                                        &block->page);
 
2183
                        }
2948
2184
                }
2949
2185
 
2950
2186
                /* Buffer-fix, I/O-fix, and X-latch the block
2957
2193
 
2958
2194
                block->page.buf_fix_count = 1;
2959
2195
                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
 
 
 
2196
                rw_lock_x_lock(&block->lock);
2964
2197
                mutex_exit(&block->mutex);
2965
 
                mutex_exit(&buf_pool->zip_mutex);
 
2198
                mutex_exit(&buf_pool_zip_mutex);
2966
2199
                buf_pool->n_pend_unzip++;
2967
2200
 
2968
 
                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 
2201
                buf_buddy_free(bpage, sizeof *bpage);
2969
2202
 
2970
 
                buf_pool_mutex_exit(buf_pool);
 
2203
                buf_pool_mutex_exit();
2971
2204
 
2972
2205
                /* Decompress the page and apply buffered operations
2973
 
                while not holding buf_pool->mutex or block->mutex. */
 
2206
                while not holding buf_pool_mutex or block->mutex. */
2974
2207
                success = buf_zip_decompress(block, srv_use_checksums);
2975
 
                ut_a(success);
2976
2208
 
2977
 
                if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
 
2209
                if (UNIV_LIKELY(success)) {
2978
2210
                        ibuf_merge_or_delete_for_page(block, space, offset,
2979
2211
                                                      zip_size, TRUE);
2980
2212
                }
2981
2213
 
2982
2214
                /* Unfix and unlatch the block. */
2983
 
                buf_pool_mutex_enter(buf_pool);
 
2215
                buf_pool_mutex_enter();
2984
2216
                mutex_enter(&block->mutex);
2985
2217
                block->page.buf_fix_count--;
2986
2218
                buf_block_set_io_fix(block, BUF_IO_NONE);
2988
2220
                buf_pool->n_pend_unzip--;
2989
2221
                rw_lock_x_unlock(&block->lock);
2990
2222
 
 
2223
                if (UNIV_UNLIKELY(!success)) {
 
2224
 
 
2225
                        buf_pool_mutex_exit();
 
2226
                        return(NULL);
 
2227
                }
 
2228
 
2991
2229
                break;
2992
2230
 
2993
2231
        case BUF_BLOCK_ZIP_FREE:
3002
2240
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3003
2241
 
3004
2242
        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
2243
        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
2244
 
3052
2245
        buf_block_buf_fix_inc(block, file, line);
 
2246
        buf_pool_mutex_exit();
 
2247
 
 
2248
        /* Check if this is the first access to the page */
 
2249
 
 
2250
        accessed = buf_page_is_accessed(&block->page);
 
2251
 
 
2252
        buf_page_set_accessed(&block->page, TRUE);
3053
2253
 
3054
2254
        mutex_exit(&block->mutex);
3055
2255
 
3056
 
        /* Check if this is the first access to the page */
3057
 
 
3058
 
        access_time = buf_page_is_accessed(&block->page);
3059
 
 
3060
 
        buf_pool_mutex_exit(buf_pool);
3061
 
 
3062
 
        buf_page_set_accessed_make_young(&block->page, access_time);
 
2256
        buf_block_make_young(&block->page);
3063
2257
 
3064
2258
#ifdef UNIV_DEBUG_FILE_ACCESSES
3065
2259
        ut_a(!block->page.file_page_was_freed);
3112
2306
 
3113
2307
        mtr_memo_push(mtr, block, fix_type);
3114
2308
 
3115
 
        if (!access_time) {
 
2309
        if (!accessed) {
3116
2310
                /* In the case of a first access, try to apply linear
3117
2311
                read-ahead */
3118
2312
 
3132
2326
@return TRUE if success */
3133
2327
UNIV_INTERN
3134
2328
ibool
3135
 
buf_page_optimistic_get(
3136
 
/*====================*/
 
2329
buf_page_optimistic_get_func(
 
2330
/*=========================*/
3137
2331
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
3138
2332
        buf_block_t*    block,  /*!< in: guessed buffer block */
3139
2333
        ib_uint64_t     modify_clock,/*!< in: modify clock value if mode is
3142
2336
        ulint           line,   /*!< in: line where called */
3143
2337
        mtr_t*          mtr)    /*!< in: mini-transaction */
3144
2338
{
3145
 
        buf_pool_t*     buf_pool;
3146
 
        unsigned        access_time;
 
2339
        ibool           accessed;
3147
2340
        ibool           success;
3148
2341
        ulint           fix_type;
3149
2342
 
3150
 
        ut_ad(block);
3151
 
        ut_ad(mtr);
3152
 
        ut_ad(mtr->state == MTR_ACTIVE);
 
2343
        ut_ad(mtr && block);
3153
2344
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3154
2345
 
3155
2346
        mutex_enter(&block->mutex);
3162
2353
        }
3163
2354
 
3164
2355
        buf_block_buf_fix_inc(block, file, line);
 
2356
        accessed = buf_page_is_accessed(&block->page);
 
2357
        buf_page_set_accessed(&block->page, TRUE);
3165
2358
 
3166
2359
        mutex_exit(&block->mutex);
3167
2360
 
3168
 
        /* Check if this is the first access to the page.
3169
 
        We do a dirty read on purpose, to avoid mutex contention.
3170
 
        This field is only used for heuristic purposes; it does not
3171
 
        affect correctness. */
 
2361
        buf_block_make_young(&block->page);
3172
2362
 
3173
 
        access_time = buf_page_is_accessed(&block->page);
3174
 
        buf_page_set_accessed_make_young(&block->page, access_time);
 
2363
        /* Check if this is the first access to the page */
3175
2364
 
3176
2365
        ut_ad(!ibuf_inside()
3177
2366
              || ibuf_page(buf_block_get_space(block),
3223
2412
#ifdef UNIV_DEBUG_FILE_ACCESSES
3224
2413
        ut_a(block->page.file_page_was_freed == FALSE);
3225
2414
#endif
3226
 
        if (UNIV_UNLIKELY(!access_time)) {
 
2415
        if (UNIV_UNLIKELY(!accessed)) {
3227
2416
                /* In the case of a first access, try to apply linear
3228
2417
                read-ahead */
3229
2418
 
3236
2425
        ut_a(ibuf_count_get(buf_block_get_space(block),
3237
2426
                            buf_block_get_page_no(block)) == 0);
3238
2427
#endif
3239
 
        buf_pool = buf_pool_from_block(block);
3240
 
        buf_pool->stat.n_page_gets++;
 
2428
        buf_pool->n_page_gets++;
3241
2429
 
3242
2430
        return(TRUE);
3243
2431
}
3258
2446
        ulint           line,   /*!< in: line where called */
3259
2447
        mtr_t*          mtr)    /*!< in: mini-transaction */
3260
2448
{
3261
 
        buf_pool_t*     buf_pool;
3262
2449
        ibool           success;
3263
2450
        ulint           fix_type;
3264
2451
 
3265
2452
        ut_ad(mtr);
3266
 
        ut_ad(mtr->state == MTR_ACTIVE);
3267
2453
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3268
2454
 
3269
2455
        mutex_enter(&block->mutex);
3287
2473
 
3288
2474
        mutex_exit(&block->mutex);
3289
2475
 
3290
 
        buf_pool = buf_pool_from_block(block);
3291
 
 
3292
 
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
3293
 
                buf_pool_mutex_enter(buf_pool);
3294
 
                buf_LRU_make_block_young(&block->page);
3295
 
                buf_pool_mutex_exit(buf_pool);
3296
 
        } else if (!buf_page_is_accessed(&block->page)) {
3297
 
                /* Above, we do a dirty read on purpose, to avoid
3298
 
                mutex contention.  The field buf_page_t::access_time
3299
 
                is only used for heuristic purposes.  Writes to the
3300
 
                field must be protected by mutex, however. */
3301
 
                ulint   time_ms = ut_time_ms();
3302
 
 
3303
 
                buf_pool_mutex_enter(buf_pool);
3304
 
                buf_page_set_accessed(&block->page, time_ms);
3305
 
                buf_pool_mutex_exit(buf_pool);
 
2476
        if (mode == BUF_MAKE_YOUNG) {
 
2477
                buf_block_make_young(&block->page);
3306
2478
        }
3307
2479
 
3308
2480
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
3341
2513
             || (ibuf_count_get(buf_block_get_space(block),
3342
2514
                                buf_block_get_page_no(block)) == 0));
3343
2515
#endif
3344
 
        buf_pool->stat.n_page_gets++;
 
2516
        buf_pool->n_page_gets++;
3345
2517
 
3346
2518
        return(TRUE);
3347
2519
}
3364
2536
        buf_block_t*    block;
3365
2537
        ibool           success;
3366
2538
        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);
 
2539
 
 
2540
        buf_pool_mutex_enter();
 
2541
        block = buf_block_hash_get(space_id, page_no);
 
2542
 
 
2543
        if (!block) {
 
2544
                buf_pool_mutex_exit();
3377
2545
                return(NULL);
3378
2546
        }
3379
2547
 
3380
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
3381
 
 
3382
2548
        mutex_enter(&block->mutex);
3383
 
        buf_pool_mutex_exit(buf_pool);
 
2549
        buf_pool_mutex_exit();
3384
2550
 
3385
2551
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3386
2552
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3423
2589
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3424
2590
        buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
3425
2591
 
3426
 
        buf_pool->stat.n_page_gets++;
 
2592
        buf_pool->n_page_gets++;
3427
2593
 
3428
2594
#ifdef UNIV_IBUF_COUNT_DEBUG
3429
2595
        ut_a(ibuf_count_get(buf_block_get_space(block),
3442
2608
        buf_page_t*     bpage)  /*!< in: block to init */
3443
2609
{
3444
2610
        bpage->flush_type = BUF_FLUSH_LRU;
 
2611
        bpage->accessed = FALSE;
3445
2612
        bpage->io_fix = BUF_IO_NONE;
3446
2613
        bpage->buf_fix_count = 0;
3447
2614
        bpage->freed_page_clock = 0;
3448
 
        bpage->access_time = 0;
3449
2615
        bpage->newest_modification = 0;
3450
2616
        bpage->oldest_modification = 0;
3451
2617
        HASH_INVALIDATE(bpage, hash);
3463
2629
        ulint           space,  /*!< in: space id */
3464
2630
        ulint           offset, /*!< in: offset of the page within space
3465
2631
                                in units of a page */
3466
 
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
3467
2632
        buf_block_t*    block)  /*!< in: block to init */
3468
2633
{
3469
2634
        buf_page_t*     hash_page;
3470
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3471
2635
 
3472
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2636
        ut_ad(buf_pool_mutex_own());
3473
2637
        ut_ad(mutex_own(&(block->mutex)));
3474
2638
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
3475
2639
 
3487
2651
 
3488
2652
        buf_block_init_low(block);
3489
2653
 
3490
 
        block->lock_hash_val = lock_rec_hash(space, offset);
3491
 
 
3492
 
        buf_page_init_low(&block->page);
 
2654
        block->lock_hash_val    = lock_rec_hash(space, offset);
3493
2655
 
3494
2656
        /* Insert into the hash table of file pages */
3495
2657
 
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 {
 
2658
        hash_page = buf_page_hash_get(space, offset);
 
2659
 
 
2660
        if (UNIV_LIKELY_NULL(hash_page)) {
3507
2661
                fprintf(stderr,
3508
2662
                        "InnoDB: Error: page %lu %lu already found"
3509
2663
                        " in the hash table: %p, %p\n",
3512
2666
                        (const void*) hash_page, (const void*) block);
3513
2667
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3514
2668
                mutex_exit(&block->mutex);
3515
 
                buf_pool_mutex_exit(buf_pool);
 
2669
                buf_pool_mutex_exit();
3516
2670
                buf_print();
3517
2671
                buf_LRU_print();
3518
2672
                buf_validate();
3521
2675
                ut_error;
3522
2676
        }
3523
2677
 
 
2678
        buf_page_init_low(&block->page);
 
2679
 
3524
2680
        ut_ad(!block->page.in_zip_hash);
3525
2681
        ut_ad(!block->page.in_page_hash);
3526
2682
        ut_d(block->page.in_page_hash = TRUE);
3527
2683
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
3528
 
                    fold, &block->page);
 
2684
                    buf_page_address_fold(space, offset), &block->page);
3529
2685
}
3530
2686
 
3531
2687
/********************************************************************//**
3547
2703
        ulint           space,  /*!< in: space id */
3548
2704
        ulint           zip_size,/*!< in: compressed page size, or 0 */
3549
2705
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
3550
 
        ib_int64_t      tablespace_version,
3551
 
                                /*!< in: prevents reading from a wrong
 
2706
        ib_int64_t      tablespace_version,/*!< in: prevents reading from a wrong
3552
2707
                                version of the tablespace in case we have done
3553
2708
                                DISCARD + IMPORT */
3554
2709
        ulint           offset) /*!< in: page number */
3555
2710
{
3556
2711
        buf_block_t*    block;
3557
 
        buf_page_t*     bpage   = NULL;
3558
 
        buf_page_t*     watch_page;
 
2712
        buf_page_t*     bpage;
3559
2713
        mtr_t           mtr;
3560
 
        ulint           fold;
3561
2714
        ibool           lru     = FALSE;
3562
2715
        void*           data;
3563
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3564
2716
 
3565
2717
        ut_ad(buf_pool);
3566
2718
 
3589
2741
            && UNIV_LIKELY(!recv_recovery_is_on())) {
3590
2742
                block = NULL;
3591
2743
        } else {
3592
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2744
                block = buf_LRU_get_free_block(0);
3593
2745
                ut_ad(block);
3594
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
3595
2746
        }
3596
2747
 
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)) {
 
2748
        buf_pool_mutex_enter();
 
2749
 
 
2750
        if (buf_page_hash_get(space, offset)) {
3603
2751
                /* The page is already in the buffer pool. */
3604
 
                watch_page = NULL;
3605
2752
err_exit:
3606
2753
                if (block) {
3607
2754
                        mutex_enter(&block->mutex);
3625
2772
        if (block) {
3626
2773
                bpage = &block->page;
3627
2774
                mutex_enter(&block->mutex);
3628
 
 
3629
 
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
3630
 
 
3631
 
                buf_page_init(space, offset, fold, block);
 
2775
                buf_page_init(space, offset, block);
3632
2776
 
3633
2777
                /* The block must be put to the LRU list, to the old blocks */
3634
2778
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3648
2792
                if (UNIV_UNLIKELY(zip_size)) {
3649
2793
                        page_zip_set_size(&block->page.zip, zip_size);
3650
2794
 
3651
 
                        /* buf_pool->mutex may be released and
 
2795
                        /* buf_pool_mutex may be released and
3652
2796
                        reacquired by buf_buddy_alloc().  Thus, we
3653
2797
                        must release block->mutex in order not to
3654
2798
                        break the latching order in the reacquisition
3655
 
                        of buf_pool->mutex.  We also must defer this
 
2799
                        of buf_pool_mutex.  We also must defer this
3656
2800
                        operation until after the block descriptor has
3657
2801
                        been added to buf_pool->LRU and
3658
2802
                        buf_pool->page_hash. */
3659
2803
                        mutex_exit(&block->mutex);
3660
 
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2804
                        data = buf_buddy_alloc(zip_size, &lru);
3661
2805
                        mutex_enter(&block->mutex);
3662
 
                        block->page.zip.data = static_cast<unsigned char *>(data);
 
2806
                        block->page.zip.data = data;
3663
2807
 
3664
2808
                        /* To maintain the invariant
3665
2809
                        block->in_unzip_LRU_list
3681
2825
                control block (bpage), in order to avoid the
3682
2826
                invocation of buf_buddy_relocate_block() on
3683
2827
                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);
 
2828
                data = buf_buddy_alloc(zip_size, &lru);
 
2829
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3689
2830
 
3690
2831
                /* If buf_buddy_alloc() allocated storage from the LRU list,
3691
 
                it released and reacquired buf_pool->mutex.  Thus, we must
 
2832
                it released and reacquired buf_pool_mutex.  Thus, we must
3692
2833
                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
 
                        }
 
2834
                if (UNIV_UNLIKELY(lru)
 
2835
                    && UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
 
2836
 
 
2837
                        /* The block was added by some other thread. */
 
2838
                        buf_buddy_free(bpage, sizeof *bpage);
 
2839
                        buf_buddy_free(data, zip_size);
 
2840
 
 
2841
                        bpage = NULL;
 
2842
                        goto func_exit;
3710
2843
                }
3711
2844
 
3712
2845
                page_zip_des_init(&bpage->zip);
3713
2846
                page_zip_set_size(&bpage->zip, zip_size);
3714
 
                bpage->zip.data = static_cast<unsigned char *>(data);
 
2847
                bpage->zip.data = data;
3715
2848
 
3716
 
                mutex_enter(&buf_pool->zip_mutex);
 
2849
                mutex_enter(&buf_pool_zip_mutex);
3717
2850
                UNIV_MEM_DESC(bpage->zip.data,
3718
2851
                              page_zip_get_size(&bpage->zip), bpage);
3719
 
 
3720
2852
                buf_page_init_low(bpage);
3721
 
 
3722
2853
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
3723
2854
                bpage->space    = space;
3724
2855
                bpage->offset   = offset;
3725
2856
 
3726
 
 
3727
2857
#ifdef UNIV_DEBUG
3728
2858
                bpage->in_page_hash = FALSE;
3729
2859
                bpage->in_zip_hash = FALSE;
3733
2863
#endif /* UNIV_DEBUG */
3734
2864
 
3735
2865
                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);
 
2866
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
2867
                            buf_page_address_fold(space, offset), bpage);
3748
2868
 
3749
2869
                /* The block must be put to the LRU list, to the old blocks */
3750
2870
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3752
2872
 
3753
2873
                buf_page_set_io_fix(bpage, BUF_IO_READ);
3754
2874
 
3755
 
                mutex_exit(&buf_pool->zip_mutex);
 
2875
                mutex_exit(&buf_pool_zip_mutex);
3756
2876
        }
3757
2877
 
3758
2878
        buf_pool->n_pend_reads++;
3759
2879
func_exit:
3760
 
        buf_pool_mutex_exit(buf_pool);
 
2880
        buf_pool_mutex_exit();
3761
2881
 
3762
2882
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
3763
2883
 
3786
2906
{
3787
2907
        buf_frame_t*    frame;
3788
2908
        buf_block_t*    block;
3789
 
        ulint           fold;
3790
2909
        buf_block_t*    free_block      = NULL;
3791
 
        ulint           time_ms         = ut_time_ms();
3792
 
        buf_pool_t*     buf_pool        = buf_pool_get(space, offset);
3793
2910
 
3794
2911
        ut_ad(mtr);
3795
 
        ut_ad(mtr->state == MTR_ACTIVE);
3796
2912
        ut_ad(space || !zip_size);
3797
2913
 
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)) {
 
2914
        free_block = buf_LRU_get_free_block(0);
 
2915
 
 
2916
        buf_pool_mutex_enter();
 
2917
 
 
2918
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2919
 
 
2920
        if (block && buf_page_in_file(&block->page)) {
3810
2921
#ifdef UNIV_IBUF_COUNT_DEBUG
3811
2922
                ut_a(ibuf_count_get(space, offset) == 0);
3812
2923
#endif
3815
2926
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3816
2927
 
3817
2928
                /* Page can be found in buf_pool */
3818
 
                buf_pool_mutex_exit(buf_pool);
 
2929
                buf_pool_mutex_exit();
3819
2930
 
3820
2931
                buf_block_free(free_block);
3821
2932
 
3836
2947
 
3837
2948
        mutex_enter(&block->mutex);
3838
2949
 
3839
 
        buf_page_init(space, offset, fold, block);
 
2950
        buf_page_init(space, offset, block);
3840
2951
 
3841
2952
        /* The block must be put to the LRU list */
3842
2953
        buf_LRU_add_block(&block->page, FALSE);
3843
2954
 
3844
2955
        buf_block_buf_fix_inc(block, __FILE__, __LINE__);
3845
 
        buf_pool->stat.n_pages_created++;
 
2956
        buf_pool->n_pages_created++;
3846
2957
 
3847
2958
        if (zip_size) {
3848
2959
                void*   data;
3849
2960
                ibool   lru;
3850
2961
 
3851
2962
                /* Prevent race conditions during buf_buddy_alloc(),
3852
 
                which may release and reacquire buf_pool->mutex,
 
2963
                which may release and reacquire buf_pool_mutex,
3853
2964
                by IO-fixing and X-latching the block. */
3854
2965
 
3855
2966
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3857
2968
 
3858
2969
                page_zip_set_size(&block->page.zip, zip_size);
3859
2970
                mutex_exit(&block->mutex);
3860
 
                /* buf_pool->mutex may be released and reacquired by
 
2971
                /* buf_pool_mutex may be released and reacquired by
3861
2972
                buf_buddy_alloc().  Thus, we must release block->mutex
3862
2973
                in order not to break the latching order in
3863
 
                the reacquisition of buf_pool->mutex.  We also must
 
2974
                the reacquisition of buf_pool_mutex.  We also must
3864
2975
                defer this operation until after the block descriptor
3865
2976
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3866
 
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2977
                data = buf_buddy_alloc(zip_size, &lru);
3867
2978
                mutex_enter(&block->mutex);
3868
 
                block->page.zip.data = static_cast<unsigned char *>(data);
 
2979
                block->page.zip.data = data;
3869
2980
 
3870
2981
                /* To maintain the invariant
3871
2982
                block->in_unzip_LRU_list
3879
2990
                rw_lock_x_unlock(&block->lock);
3880
2991
        }
3881
2992
 
3882
 
        buf_page_set_accessed(&block->page, time_ms);
3883
 
 
3884
 
        buf_pool_mutex_exit(buf_pool);
 
2993
        buf_pool_mutex_exit();
3885
2994
 
3886
2995
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3887
2996
 
 
2997
        buf_page_set_accessed(&block->page, TRUE);
 
2998
 
3888
2999
        mutex_exit(&block->mutex);
3889
3000
 
3890
3001
        /* Delete possible entries for the page from the insert buffer:
3893
3004
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3894
3005
 
3895
3006
        /* Flush pages from the end of the LRU list if necessary */
3896
 
        buf_flush_free_margin(buf_pool);
 
3007
        buf_flush_free_margin();
3897
3008
 
3898
3009
        frame = block->frame;
3899
3010
 
3929
3040
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
3930
3041
{
3931
3042
        enum buf_io_fix io_type;
3932
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3933
3043
        const ibool     uncompressed = (buf_page_get_state(bpage)
3934
3044
                                        == BUF_BLOCK_FILE_PAGE);
3935
3045
 
4065
3175
                }
4066
3176
        }
4067
3177
 
4068
 
        buf_pool_mutex_enter(buf_pool);
 
3178
        buf_pool_mutex_enter();
4069
3179
        mutex_enter(buf_page_get_mutex(bpage));
4070
3180
 
4071
3181
#ifdef UNIV_IBUF_COUNT_DEBUG
4091
3201
 
4092
3202
                ut_ad(buf_pool->n_pend_reads > 0);
4093
3203
                buf_pool->n_pend_reads--;
4094
 
                buf_pool->stat.n_pages_read++;
 
3204
                buf_pool->n_pages_read++;
4095
3205
 
4096
3206
                if (uncompressed) {
4097
3207
                        rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock,
4111
3221
                                             BUF_IO_WRITE);
4112
3222
                }
4113
3223
 
4114
 
                buf_pool->stat.n_pages_written++;
 
3224
                buf_pool->n_pages_written++;
4115
3225
 
4116
3226
                break;
4117
3227
 
4129
3239
#endif /* UNIV_DEBUG */
4130
3240
 
4131
3241
        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
 
3242
        buf_pool_mutex_exit();
 
3243
}
 
3244
 
 
3245
/*********************************************************************//**
 
3246
Invalidates the file pages in the buffer pool when an archive recovery is
 
3247
completed. All the file pages buffered must be in a replaceable state when
 
3248
this function is called: not latched and not modified. */
 
3249
UNIV_INTERN
4174
3250
void
4175
 
buf_pool_invalidate_instance(
4176
 
/*=========================*/
4177
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3251
buf_pool_invalidate(void)
 
3252
/*=====================*/
4178
3253
{
4179
 
        ibool           freed;
4180
 
        int     i;
4181
 
 
4182
 
        buf_pool_mutex_enter(buf_pool);
4183
 
 
4184
 
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
4185
 
 
4186
 
                /* As this function is called during startup and
4187
 
                during redo application phase during recovery, InnoDB
4188
 
                is single threaded (apart from IO helper threads) at
4189
 
                this stage. No new write batch can be in intialization
4190
 
                stage at this point. */
4191
 
                ut_ad(buf_pool->init_flush[i] == FALSE);
4192
 
 
4193
 
                /* However, it is possible that a write batch that has
4194
 
                been posted earlier is still not complete. For buffer
4195
 
                pool invalidation to proceed we must ensure there is NO
4196
 
                write activity happening. */
4197
 
                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);
4201
 
                }
4202
 
        }
4203
 
 
4204
 
        buf_pool_mutex_exit(buf_pool);
4205
 
 
4206
 
        ut_ad(buf_all_freed_instance(buf_pool));
 
3254
        ibool   freed;
 
3255
 
 
3256
        ut_ad(buf_all_freed());
4207
3257
 
4208
3258
        freed = TRUE;
4209
3259
 
4210
3260
        while (freed) {
4211
 
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
 
3261
                freed = buf_LRU_search_and_free_block(100);
4212
3262
        }
4213
3263
 
4214
 
        buf_pool_mutex_enter(buf_pool);
 
3264
        buf_pool_mutex_enter();
4215
3265
 
4216
3266
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
4217
3267
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
4218
3268
 
4219
 
        buf_pool->freed_page_clock = 0;
4220
 
        buf_pool->LRU_old = NULL;
4221
 
        buf_pool->LRU_old_len = 0;
4222
 
        buf_pool->LRU_flush_ended = 0;
4223
 
 
4224
 
        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
 
        }
 
3269
        buf_pool_mutex_exit();
4244
3270
}
4245
3271
 
4246
3272
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4247
3273
/*********************************************************************//**
4248
 
Validates data in one buffer pool instance
 
3274
Validates the buffer buf_pool data structure.
4249
3275
@return TRUE */
4250
 
static
 
3276
UNIV_INTERN
4251
3277
ibool
4252
 
buf_pool_validate_instance(
4253
 
/*=======================*/
4254
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3278
buf_validate(void)
 
3279
/*==============*/
4255
3280
{
4256
3281
        buf_page_t*     b;
4257
3282
        buf_chunk_t*    chunk;
4266
3291
 
4267
3292
        ut_ad(buf_pool);
4268
3293
 
4269
 
        buf_pool_mutex_enter(buf_pool);
 
3294
        buf_pool_mutex_enter();
4270
3295
 
4271
3296
        chunk = buf_pool->chunks;
4272
3297
 
4291
3316
                                break;
4292
3317
 
4293
3318
                        case BUF_BLOCK_FILE_PAGE:
4294
 
                                ut_a(buf_page_hash_get(buf_pool,
4295
 
                                                       buf_block_get_space(
 
3319
                                ut_a(buf_page_hash_get(buf_block_get_space(
4296
3320
                                                               block),
4297
3321
                                                       buf_block_get_page_no(
4298
3322
                                                               block))
4339
3363
                                }
4340
3364
 
4341
3365
                                n_lru++;
 
3366
 
 
3367
                                if (block->page.oldest_modification > 0) {
 
3368
                                        n_flush++;
 
3369
                                }
 
3370
 
4342
3371
                                break;
4343
3372
 
4344
3373
                        case BUF_BLOCK_NOT_USED:
4356
3385
                }
4357
3386
        }
4358
3387
 
4359
 
        mutex_enter(&buf_pool->zip_mutex);
 
3388
        mutex_enter(&buf_pool_zip_mutex);
4360
3389
 
4361
3390
        /* Check clean compressed-only blocks. */
4362
3391
 
4377
3406
                        ut_error;
4378
3407
                        break;
4379
3408
                }
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
3409
                ut_a(!b->oldest_modification);
4385
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3410
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4386
3411
 
4387
3412
                n_lru++;
4388
3413
                n_zip++;
4389
3414
        }
4390
3415
 
4391
 
        /* Check dirty blocks. */
 
3416
        /* Check dirty compressed-only blocks. */
4392
3417
 
4393
 
        buf_flush_list_mutex_enter(buf_pool);
4394
3418
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4395
3419
             b = UT_LIST_GET_NEXT(list, b)) {
4396
3420
                ut_ad(b->in_flush_list);
4397
 
                ut_a(b->oldest_modification);
4398
 
                n_flush++;
4399
3421
 
4400
3422
                switch (buf_page_get_state(b)) {
4401
3423
                case BUF_BLOCK_ZIP_DIRTY:
 
3424
                        ut_a(b->oldest_modification);
4402
3425
                        n_lru++;
 
3426
                        n_flush++;
4403
3427
                        n_zip++;
4404
3428
                        switch (buf_page_get_io_fix(b)) {
4405
3429
                        case BUF_IO_NONE:
4406
3430
                        case BUF_IO_READ:
4407
3431
                                break;
 
3432
 
4408
3433
                        case BUF_IO_WRITE:
4409
3434
                                switch (buf_page_get_flush_type(b)) {
4410
3435
                                case BUF_FLUSH_LRU:
4434
3459
                        ut_error;
4435
3460
                        break;
4436
3461
                }
4437
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3462
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4438
3463
        }
4439
3464
 
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);
 
3465
        mutex_exit(&buf_pool_zip_mutex);
4445
3466
 
4446
3467
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
4447
3468
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
4457
3478
                        (ulong) n_free);
4458
3479
                ut_error;
4459
3480
        }
 
3481
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4460
3482
 
4461
3483
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
4462
3484
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
4463
3485
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
4464
3486
 
4465
 
        buf_pool_mutex_exit(buf_pool);
 
3487
        buf_pool_mutex_exit();
4466
3488
 
4467
3489
        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
 
 
 
3490
        ut_a(buf_flush_validate());
 
3491
 
 
3492
        return(TRUE);
 
3493
}
4493
3494
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
4494
3495
 
4495
3496
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4496
3497
/*********************************************************************//**
4497
 
Prints info of the buffer buf_pool data structure for one instance. */
4498
 
static
 
3498
Prints info of the buffer buf_pool data structure. */
 
3499
UNIV_INTERN
4499
3500
void
4500
 
buf_print_instance(
4501
 
/*===============*/
4502
 
        buf_pool_t*     buf_pool)
 
3501
buf_print(void)
 
3502
/*===========*/
4503
3503
{
4504
 
        index_id_t*     index_ids;
 
3504
        dulint*         index_ids;
4505
3505
        ulint*          counts;
4506
3506
        ulint           size;
4507
3507
        ulint           i;
4508
3508
        ulint           j;
4509
 
        index_id_t      id;
 
3509
        dulint          id;
4510
3510
        ulint           n_found;
4511
3511
        buf_chunk_t*    chunk;
4512
3512
        dict_index_t*   index;
4515
3515
 
4516
3516
        size = buf_pool->curr_size;
4517
3517
 
4518
 
        index_ids = mem_alloc(size * sizeof *index_ids);
 
3518
        index_ids = mem_alloc(sizeof(dulint) * size);
4519
3519
        counts = mem_alloc(sizeof(ulint) * size);
4520
3520
 
4521
 
        buf_pool_mutex_enter(buf_pool);
4522
 
        buf_flush_list_mutex_enter(buf_pool);
 
3521
        buf_pool_mutex_enter();
4523
3522
 
4524
3523
        fprintf(stderr,
4525
3524
                "buf_pool size %lu\n"
4529
3528
                "n pending decompressions %lu\n"
4530
3529
                "n pending reads %lu\n"
4531
3530
                "n pending flush LRU %lu list %lu single page %lu\n"
4532
 
                "pages made young %lu, not young %lu\n"
4533
3531
                "pages read %lu, created %lu, written %lu\n",
4534
3532
                (ulong) size,
4535
3533
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4540
3538
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU],
4541
3539
                (ulong) buf_pool->n_flush[BUF_FLUSH_LIST],
4542
3540
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE],
4543
 
                (ulong) buf_pool->stat.n_pages_made_young,
4544
 
                (ulong) buf_pool->stat.n_pages_not_made_young,
4545
 
                (ulong) buf_pool->stat.n_pages_read,
4546
 
                (ulong) buf_pool->stat.n_pages_created,
4547
 
                (ulong) buf_pool->stat.n_pages_written);
4548
 
 
4549
 
        buf_flush_list_mutex_exit(buf_pool);
 
3541
                (ulong) buf_pool->n_pages_read, buf_pool->n_pages_created,
 
3542
                (ulong) buf_pool->n_pages_written);
4550
3543
 
4551
3544
        /* Count the number of blocks belonging to each index in the buffer */
4552
3545
 
4570
3563
 
4571
3564
                                while (j < n_found) {
4572
3565
 
4573
 
                                        if (index_ids[j] == id) {
 
3566
                                        if (ut_dulint_cmp(index_ids[j],
 
3567
                                                          id) == 0) {
4574
3568
                                                counts[j]++;
4575
3569
 
4576
3570
                                                break;
4587
3581
                }
4588
3582
        }
4589
3583
 
4590
 
        buf_pool_mutex_exit(buf_pool);
 
3584
        buf_pool_mutex_exit();
4591
3585
 
4592
3586
        for (i = 0; i < n_found; i++) {
4593
3587
                index = dict_index_get_if_in_cache(index_ids[i]);
4594
3588
 
4595
3589
                fprintf(stderr,
4596
 
                        "Block count for index %llu in buffer is about %lu",
4597
 
                        (ullint) index_ids[i],
 
3590
                        "Block count for index %lu in buffer is about %lu",
 
3591
                        (ulong) ut_dulint_get_low(index_ids[i]),
4598
3592
                        (ulong) counts[i]);
4599
3593
 
4600
3594
                if (index) {
4608
3602
        mem_free(index_ids);
4609
3603
        mem_free(counts);
4610
3604
 
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
 
        }
 
3605
        ut_a(buf_validate());
4629
3606
}
4630
3607
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
4631
3608
 
4635
3612
@return number of latched pages */
4636
3613
UNIV_INTERN
4637
3614
ulint
4638
 
buf_get_latched_pages_number_instance(
4639
 
/*==================================*/
4640
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3615
buf_get_latched_pages_number(void)
 
3616
/*==============================*/
4641
3617
{
 
3618
        buf_chunk_t*    chunk;
4642
3619
        buf_page_t*     b;
4643
3620
        ulint           i;
4644
 
        buf_chunk_t*    chunk;
4645
3621
        ulint           fixed_pages_number = 0;
4646
3622
 
4647
 
        buf_pool_mutex_enter(buf_pool);
 
3623
        buf_pool_mutex_enter();
4648
3624
 
4649
3625
        chunk = buf_pool->chunks;
4650
3626
 
4673
3649
                }
4674
3650
        }
4675
3651
 
4676
 
        mutex_enter(&buf_pool->zip_mutex);
 
3652
        mutex_enter(&buf_pool_zip_mutex);
4677
3653
 
4678
3654
        /* Traverse the lists of clean and dirty compressed-only blocks. */
4679
3655
 
4688
3664
                }
4689
3665
        }
4690
3666
 
4691
 
        buf_flush_list_mutex_enter(buf_pool);
4692
3667
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4693
3668
             b = UT_LIST_GET_NEXT(list, b)) {
4694
3669
                ut_ad(b->in_flush_list);
4714
3689
                }
4715
3690
        }
4716
3691
 
4717
 
        buf_flush_list_mutex_exit(buf_pool);
4718
 
        mutex_exit(&buf_pool->zip_mutex);
4719
 
        buf_pool_mutex_exit(buf_pool);
 
3692
        mutex_exit(&buf_pool_zip_mutex);
 
3693
        buf_pool_mutex_exit();
4720
3694
 
4721
3695
        return(fixed_pages_number);
4722
3696
}
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
3697
#endif /* UNIV_DEBUG */
4748
3698
 
4749
3699
/*********************************************************************//**
4754
3704
buf_get_n_pending_ios(void)
4755
3705
/*=======================*/
4756
3706
{
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);
 
3707
        return(buf_pool->n_pend_reads
 
3708
               + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3709
               + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3710
               + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4773
3711
}
4774
3712
 
4775
3713
/*********************************************************************//**
4781
3719
buf_get_modified_ratio_pct(void)
4782
3720
/*============================*/
4783
3721
{
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
 
  
 
3722
        ulint   ratio;
 
3723
 
 
3724
        buf_pool_mutex_enter();
 
3725
 
 
3726
        ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
 
3727
                / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
 
3728
                   + UT_LIST_GET_LEN(buf_pool->free));
 
3729
 
4793
3730
        /* 1 + is there to avoid division by zero */
4794
3731
 
 
3732
        buf_pool_mutex_exit();
 
3733
 
4795
3734
        return(ratio);
4796
3735
}
4797
3736
 
4798
3737
/*********************************************************************//**
4799
3738
Prints info of the buffer i/o. */
4800
 
static
 
3739
UNIV_INTERN
4801
3740
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 */
 
3741
buf_print_io(
 
3742
/*=========*/
 
3743
        FILE*   file)   /*!< in/out: buffer where to print */
4806
3744
{
4807
3745
        time_t  current_time;
4808
3746
        double  time_elapsed;
4809
 
        ulint   n_gets_diff;
 
3747
        ulint   size;
4810
3748
 
4811
3749
        ut_ad(buf_pool);
 
3750
        size = buf_pool->curr_size;
4812
3751
 
4813
 
        buf_pool_mutex_enter(buf_pool);
4814
 
        buf_flush_list_mutex_enter(buf_pool);
 
3752
        buf_pool_mutex_enter();
4815
3753
 
4816
3754
        fprintf(file,
4817
3755
                "Buffer pool size   %lu\n"
4818
3756
                "Free buffers       %lu\n"
4819
3757
                "Database pages     %lu\n"
4820
 
                "Old database pages %lu\n"
4821
3758
                "Modified db pages  %lu\n"
4822
3759
                "Pending reads %lu\n"
4823
3760
                "Pending writes: LRU %lu, flush list %lu, single page %lu\n",
4824
 
                (ulong) buf_pool->curr_size,
 
3761
                (ulong) size,
4825
3762
                (ulong) UT_LIST_GET_LEN(buf_pool->free),
4826
3763
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4827
 
                (ulong) buf_pool->LRU_old_len,
4828
3764
                (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
4829
3765
                (ulong) buf_pool->n_pend_reads,
4830
3766
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
4833
3769
                + buf_pool->init_flush[BUF_FLUSH_LIST],
4834
3770
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4835
3771
 
4836
 
        buf_flush_list_mutex_exit(buf_pool);
4837
 
 
4838
3772
        current_time = time(NULL);
4839
3773
        time_elapsed = 0.001 + difftime(current_time,
4840
3774
                                        buf_pool->last_printout_time);
 
3775
        buf_pool->last_printout_time = current_time;
4841
3776
 
4842
3777
        fprintf(file,
4843
 
                "Pages made young %lu, not young %lu\n"
4844
 
                "%.2f youngs/s, %.2f non-youngs/s\n"
4845
3778
                "Pages read %lu, created %lu, written %lu\n"
4846
3779
                "%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
4847
 
                (ulong) buf_pool->stat.n_pages_made_young,
4848
 
                (ulong) buf_pool->stat.n_pages_not_made_young,
4849
 
                (buf_pool->stat.n_pages_made_young
4850
 
                 - buf_pool->old_stat.n_pages_made_young)
4851
 
                / time_elapsed,
4852
 
                (buf_pool->stat.n_pages_not_made_young
4853
 
                 - buf_pool->old_stat.n_pages_not_made_young)
4854
 
                / time_elapsed,
4855
 
                (ulong) buf_pool->stat.n_pages_read,
4856
 
                (ulong) buf_pool->stat.n_pages_created,
4857
 
                (ulong) buf_pool->stat.n_pages_written,
4858
 
                (buf_pool->stat.n_pages_read
4859
 
                 - buf_pool->old_stat.n_pages_read)
4860
 
                / time_elapsed,
4861
 
                (buf_pool->stat.n_pages_created
4862
 
                 - buf_pool->old_stat.n_pages_created)
4863
 
                / time_elapsed,
4864
 
                (buf_pool->stat.n_pages_written
4865
 
                 - buf_pool->old_stat.n_pages_written)
 
3780
                (ulong) buf_pool->n_pages_read,
 
3781
                (ulong) buf_pool->n_pages_created,
 
3782
                (ulong) buf_pool->n_pages_written,
 
3783
                (buf_pool->n_pages_read - buf_pool->n_pages_read_old)
 
3784
                / time_elapsed,
 
3785
                (buf_pool->n_pages_created - buf_pool->n_pages_created_old)
 
3786
                / time_elapsed,
 
3787
                (buf_pool->n_pages_written - buf_pool->n_pages_written_old)
4866
3788
                / time_elapsed);
4867
3789
 
4868
 
        n_gets_diff = buf_pool->stat.n_page_gets
4869
 
                    - buf_pool->old_stat.n_page_gets;
4870
 
 
4871
 
        if (n_gets_diff) {
4872
 
                fprintf(file,
4873
 
                        "Buffer pool hit rate %lu / 1000,"
4874
 
                        " young-making rate %lu / 1000 not %lu / 1000\n",
4875
 
                        (ulong)
4876
 
                        (1000 - ((1000 * (buf_pool->stat.n_pages_read
4877
 
                                          - buf_pool->old_stat.n_pages_read))
4878
 
                                 / (buf_pool->stat.n_page_gets
4879
 
                                    - buf_pool->old_stat.n_page_gets))),
4880
 
                        (ulong)
4881
 
                        (1000 * (buf_pool->stat.n_pages_made_young
4882
 
                                 - buf_pool->old_stat.n_pages_made_young)
4883
 
                         / n_gets_diff),
4884
 
                        (ulong)
4885
 
                        (1000 * (buf_pool->stat.n_pages_not_made_young
4886
 
                                 - buf_pool->old_stat.n_pages_not_made_young)
4887
 
                         / n_gets_diff));
 
3790
        if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
 
3791
                fprintf(file, "Buffer pool hit rate %lu / 1000\n",
 
3792
                        (ulong)
 
3793
                        (1000 - ((1000 * (buf_pool->n_pages_read
 
3794
                                          - buf_pool->n_pages_read_old))
 
3795
                                 / (buf_pool->n_page_gets
 
3796
                                    - buf_pool->n_page_gets_old))));
4888
3797
        } else {
4889
3798
                fputs("No buffer pool page gets since the last printout\n",
4890
3799
                      file);
4891
3800
        }
4892
3801
 
4893
 
        /* Statistics about read ahead algorithm */
4894
 
        fprintf(file, "Pages read ahead %.2f/s,"
4895
 
                " evicted without access %.2f/s\n",
4896
 
                (buf_pool->stat.n_ra_pages_read
4897
 
                - buf_pool->old_stat.n_ra_pages_read)
4898
 
                / time_elapsed,
4899
 
                (buf_pool->stat.n_ra_pages_evicted
4900
 
                - buf_pool->old_stat.n_ra_pages_evicted)
4901
 
                / time_elapsed);
 
3802
        buf_pool->n_page_gets_old = buf_pool->n_page_gets;
 
3803
        buf_pool->n_pages_read_old = buf_pool->n_pages_read;
 
3804
        buf_pool->n_pages_created_old = buf_pool->n_pages_created;
 
3805
        buf_pool->n_pages_written_old = buf_pool->n_pages_written;
4902
3806
 
4903
3807
        /* Print some values to help us with visualizing what is
4904
3808
        happening with LRU eviction. */
4905
3809
        fprintf(file,
4906
3810
                "LRU len: %lu, unzip_LRU len: %lu\n"
4907
3811
                "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)),
 
3812
                UT_LIST_GET_LEN(buf_pool->LRU),
 
3813
                UT_LIST_GET_LEN(buf_pool->unzip_LRU),
4910
3814
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
4911
3815
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
4912
3816
 
4913
 
        buf_refresh_io_stats(buf_pool);
4914
 
        buf_pool_mutex_exit(buf_pool);
 
3817
        buf_pool_mutex_exit();
 
3818
}
 
3819
 
 
3820
/**********************************************************************//**
 
3821
Refreshes the statistics used to print per-second averages. */
 
3822
UNIV_INTERN
 
3823
void
 
3824
buf_refresh_io_stats(void)
 
3825
/*======================*/
 
3826
{
 
3827
        buf_pool->last_printout_time = time(NULL);
 
3828
        buf_pool->n_page_gets_old = buf_pool->n_page_gets;
 
3829
        buf_pool->n_pages_read_old = buf_pool->n_pages_read;
 
3830
        buf_pool->n_pages_created_old = buf_pool->n_pages_created;
 
3831
        buf_pool->n_pages_written_old = buf_pool->n_pages_written;
4915
3832
}
4916
3833
 
4917
3834
/*********************************************************************//**
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
 
        }
4933
 
}
4934
 
 
4935
 
/**********************************************************************//**
4936
 
Refreshes the statistics used to print per-second averages. */
4937
 
UNIV_INTERN
4938
 
void
4939
 
buf_refresh_io_stats(
4940
 
/*=================*/
4941
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
4942
 
{
4943
 
        buf_pool->last_printout_time = ut_time();
4944
 
        buf_pool->old_stat = buf_pool->stat;
4945
 
}
4946
 
 
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 */
 
3835
Asserts that all file pages in the buffer are in a replaceable state.
 
3836
@return TRUE */
4968
3837
UNIV_INTERN
4969
3838
ibool
4970
3839
buf_all_freed(void)
4971
3840
/*===============*/
4972
3841
{
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);
 
3842
        buf_chunk_t*    chunk;
 
3843
        ulint           i;
 
3844
 
 
3845
        ut_ad(buf_pool);
 
3846
 
 
3847
        buf_pool_mutex_enter();
 
3848
 
 
3849
        chunk = buf_pool->chunks;
 
3850
 
 
3851
        for (i = buf_pool->n_chunks; i--; chunk++) {
 
3852
 
 
3853
                const buf_block_t* block = buf_chunk_not_freed(chunk);
 
3854
 
 
3855
                if (UNIV_LIKELY_NULL(block)) {
 
3856
                        fprintf(stderr,
 
3857
                                "Page %lu %lu still fixed or dirty\n",
 
3858
                                (ulong) block->page.space,
 
3859
                                (ulong) block->page.offset);
 
3860
                        ut_error;
4982
3861
                }
4983
 
        }
 
3862
        }
 
3863
 
 
3864
        buf_pool_mutex_exit();
4984
3865
 
4985
3866
        return(TRUE);
4986
3867
}
4987
 
  
 
3868
 
4988
3869
/*********************************************************************//**
4989
3870
Checks that there currently are no pending i/o-operations for the buffer
4990
3871
pool.
4994
3875
buf_pool_check_no_pending_io(void)
4995
3876
/*==============================*/
4996
3877
{
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
 
                }
 
3878
        ibool   ret;
 
3879
 
 
3880
        buf_pool_mutex_enter();
 
3881
 
 
3882
        if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3883
            + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3884
            + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
 
3885
                ret = FALSE;
 
3886
        } else {
 
3887
                ret = TRUE;
5014
3888
        }
5015
3889
 
5016
 
        buf_pool_mutex_exit_all();
 
3890
        buf_pool_mutex_exit();
5017
3891
 
5018
3892
        return(ret);
5019
3893
}
5020
3894
 
5021
 
#if 0
5022
 
Code currently not used
5023
3895
/*********************************************************************//**
5024
3896
Gets the current length of the free list of buffer blocks.
5025
3897
@return length of the free list */
5030
3902
{
5031
3903
        ulint   len;
5032
3904
 
5033
 
        buf_pool_mutex_enter(buf_pool);
 
3905
        buf_pool_mutex_enter();
5034
3906
 
5035
3907
        len = UT_LIST_GET_LEN(buf_pool->free);
5036
3908
 
5037
 
        buf_pool_mutex_exit(buf_pool);
 
3909
        buf_pool_mutex_exit();
5038
3910
 
5039
3911
        return(len);
5040
3912
}
5041
 
#endif
5042
 
 
5043
3913
#else /* !UNIV_HOTBACKUP */
5044
3914
/********************************************************************//**
5045
3915
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */