~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-10-13 17:53:36 UTC
  • mto: This revision was merged to the branch mainline in revision 1845.
  • Revision ID: mordred@inaugust.com-20101013175336-amzhjftgztblvua5
Updated pandora-build files to version 0.161

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.
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
4
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
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 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
245
 
249
246
/** The buffer buf_pool of the database */
250
 
UNIV_INTERN buf_pool_t* buf_pool_ptr[MAX_BUFFER_POOLS];
 
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 = 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
{
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
 
                buf_pool->chunks = chunk = mem_zalloc(sizeof *chunk);
1217
 
 
1218
 
                UT_LIST_INIT(buf_pool->free);
1219
 
 
1220
 
                if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
1221
 
                        mem_free(chunk);
1222
 
                        mem_free(buf_pool);
1223
 
 
1224
 
                        buf_pool_mutex_exit(buf_pool);
1225
 
 
1226
 
                        return(DB_ERROR);
1227
 
                }
1228
 
 
1229
 
                buf_pool->instance_no = instance_no;
1230
 
                buf_pool->old_pool_size = buf_pool_size;
1231
 
                buf_pool->curr_size = chunk->size;
1232
 
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1233
 
 
1234
 
                buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
1235
 
                buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
1236
 
                
1237
 
                buf_pool->last_printout_time = ut_time();
 
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);
1238
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
 
1239
962
        /* 2. Initialize flushing fields
1240
963
        -------------------------------- */
1241
964
 
1242
 
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1243
 
                     SYNC_BUF_FLUSH_LIST);
1244
 
 
1245
965
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
1246
966
                buf_pool->no_flush[i] = os_event_create(NULL);
1247
967
        }
1248
968
 
 
969
        buf_pool->ulint_clock = 1;
 
970
 
1249
971
        /* 3. Initialize LRU fields
1250
972
        --------------------------- */
1251
 
 
1252
 
        /* All fields are initialized by mem_zalloc(). */
1253
 
 
1254
 
        buf_pool_mutex_exit(buf_pool);
1255
 
 
1256
 
        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);
1257
984
}
1258
985
 
1259
986
/********************************************************************//**
1260
 
free one buffer pool instance */
1261
 
static
 
987
Frees the buffer pool at shutdown.  This must not be invoked before
 
988
freeing all mutexes. */
 
989
UNIV_INTERN
1262
990
void
1263
 
buf_pool_free_instance(
1264
 
/*===================*/
1265
 
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
1266
 
                                        to free */
 
991
buf_pool_free(void)
 
992
/*===============*/
1267
993
{
1268
994
        buf_chunk_t*    chunk;
1269
995
        buf_chunk_t*    chunks;
1277
1003
                os_mem_free_large(chunk->mem, chunk->mem_size);
1278
1004
        }
1279
1005
 
1280
 
        mem_free(buf_pool->chunks);
1281
 
        hash_table_free(buf_pool->page_hash);
1282
 
        hash_table_free(buf_pool->zip_hash);
1283
 
        mem_free(buf_pool);
1284
 
        buf_pool = NULL;
1285
 
}
1286
 
 
1287
 
/********************************************************************//**
1288
 
Creates the buffer pool.
1289
 
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
1290
 
UNIV_INTERN
1291
 
ulint
1292
 
buf_pool_init(
1293
 
/*==========*/
1294
 
        ulint   total_size,     /*!< in: size of the total pool in bytes */
1295
 
        ulint   n_instances)    /*!< in: number of instances */
1296
 
{
1297
 
        ulint   i;
1298
 
 
1299
 
        /* We create an extra buffer pool instance, this instance is used
1300
 
        for flushing the flush lists, to keep track of n_flush for all
1301
 
        the buffer pools and also used as a waiting object during flushing. */
1302
 
        for (i = 0; i < n_instances; i++) {
1303
 
                buf_pool_t*     ptr;
1304
 
                ulint           size;
1305
 
 
1306
 
                ptr = mem_zalloc(sizeof(*ptr));
1307
 
 
1308
 
                size = total_size / n_instances;
1309
 
 
1310
 
                buf_pool_ptr[i] = ptr;
1311
 
 
1312
 
                if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
1313
 
 
1314
 
                        mem_free(buf_pool_ptr[i]);
1315
 
 
1316
 
                        /* Free all the instances created so far. */
1317
 
                        buf_pool_free(i);
1318
 
 
1319
 
                        return(DB_ERROR);
1320
 
                }
1321
 
        }
1322
 
 
1323
 
        buf_pool_set_sizes();
1324
 
        buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
1325
 
 
1326
 
        btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
1327
 
 
1328
 
        return(DB_SUCCESS);
1329
 
}
1330
 
 
1331
 
/********************************************************************//**
1332
 
Frees the buffer pool at shutdown.  This must not be invoked before
1333
 
freeing all mutexes. */
1334
 
UNIV_INTERN
1335
 
void
1336
 
buf_pool_free(
1337
 
/*==========*/
1338
 
        ulint   n_instances)    /*!< in: numbere of instances to free */
1339
 
{
1340
 
        ulint   i;
1341
 
 
1342
 
        for (i = 0; i < n_instances; i++) {
1343
 
                buf_pool_free_instance(buf_pool_from_array(i));
1344
 
                buf_pool_ptr[i] = NULL;
1345
 
        }
1346
 
}
1347
 
 
1348
 
/********************************************************************//**
1349
 
Drops adaptive hash index for a buffer pool instance. */
1350
 
static
1351
 
void
1352
 
buf_pool_drop_hash_index_instance(
1353
 
/*==============================*/
1354
 
        buf_pool_t*     buf_pool,               /*!< in: buffer pool instance */
1355
 
        ibool*          released_search_latch)  /*!< out: flag for signalling
1356
 
                                                whether the search latch was
1357
 
                                                released */
1358
 
{
1359
 
        buf_chunk_t*    chunks  = buf_pool->chunks;
1360
 
        buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
1361
 
 
1362
 
        while (--chunk >= chunks) {
1363
 
                ulint           i;
1364
 
                buf_block_t*    block   = chunk->blocks;
1365
 
 
1366
 
                for (i = chunk->size; i--; block++) {
1367
 
                        /* block->is_hashed cannot be modified
1368
 
                        when we have an x-latch on btr_search_latch;
1369
 
                        see the comment in buf0buf.h */
1370
 
                        
1371
 
                        if (!block->is_hashed) {
1372
 
                                continue;
1373
 
                        }
1374
 
                        
1375
 
                        /* To follow the latching order, we
1376
 
                        have to release btr_search_latch
1377
 
                        before acquiring block->latch. */
1378
 
                        rw_lock_x_unlock(&btr_search_latch);
1379
 
                        /* When we release the search latch,
1380
 
                        we must rescan all blocks, because
1381
 
                        some may become hashed again. */
1382
 
                        *released_search_latch = TRUE;
1383
 
                        
1384
 
                        rw_lock_x_lock(&block->lock);
1385
 
                        
1386
 
                        /* This should be guaranteed by the
1387
 
                        callers, which will be holding
1388
 
                        btr_search_enabled_mutex. */
1389
 
                        ut_ad(!btr_search_enabled);
1390
 
                        
1391
 
                        /* Because we did not buffer-fix the
1392
 
                        block by calling buf_block_get_gen(),
1393
 
                        it is possible that the block has been
1394
 
                        allocated for some other use after
1395
 
                        btr_search_latch was released above.
1396
 
                        We do not care which file page the
1397
 
                        block is mapped to.  All we want to do
1398
 
                        is to drop any hash entries referring
1399
 
                        to the page. */
1400
 
                        
1401
 
                        /* It is possible that
1402
 
                        block->page.state != BUF_FILE_PAGE.
1403
 
                        Even that does not matter, because
1404
 
                        btr_search_drop_page_hash_index() will
1405
 
                        check block->is_hashed before doing
1406
 
                        anything.  block->is_hashed can only
1407
 
                        be set on uncompressed file pages. */
1408
 
                        
1409
 
                        btr_search_drop_page_hash_index(block);
1410
 
                        
1411
 
                        rw_lock_x_unlock(&block->lock);
1412
 
                        
1413
 
                        rw_lock_x_lock(&btr_search_latch);
1414
 
                        
1415
 
                        ut_ad(!btr_search_enabled);
1416
 
                }
1417
 
        }
1418
 
}
1419
 
 
 
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
1290
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *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 = 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
2244
 
3012
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);
3013
2253
 
3014
2254
        mutex_exit(&block->mutex);
3015
2255
 
3016
 
        /* Check if this is the first access to the page */
3017
 
 
3018
 
        access_time = buf_page_is_accessed(&block->page);
3019
 
 
3020
 
        buf_pool_mutex_exit(buf_pool);
3021
 
 
3022
 
        buf_page_set_accessed_make_young(&block->page, access_time);
 
2256
        buf_block_make_young(&block->page);
3023
2257
 
3024
2258
#ifdef UNIV_DEBUG_FILE_ACCESSES
3025
2259
        ut_a(!block->page.file_page_was_freed);
3072
2306
 
3073
2307
        mtr_memo_push(mtr, block, fix_type);
3074
2308
 
3075
 
        if (!access_time) {
 
2309
        if (!accessed) {
3076
2310
                /* In the case of a first access, try to apply linear
3077
2311
                read-ahead */
3078
2312
 
3092
2326
@return TRUE if success */
3093
2327
UNIV_INTERN
3094
2328
ibool
3095
 
buf_page_optimistic_get(
3096
 
/*====================*/
 
2329
buf_page_optimistic_get_func(
 
2330
/*=========================*/
3097
2331
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
3098
2332
        buf_block_t*    block,  /*!< in: guessed buffer block */
3099
2333
        ib_uint64_t     modify_clock,/*!< in: modify clock value if mode is
3102
2336
        ulint           line,   /*!< in: line where called */
3103
2337
        mtr_t*          mtr)    /*!< in: mini-transaction */
3104
2338
{
3105
 
        buf_pool_t*     buf_pool;
3106
 
        unsigned        access_time;
 
2339
        ibool           accessed;
3107
2340
        ibool           success;
3108
2341
        ulint           fix_type;
3109
2342
 
3110
 
        ut_ad(block);
3111
 
        ut_ad(mtr);
3112
 
        ut_ad(mtr->state == MTR_ACTIVE);
 
2343
        ut_ad(mtr && block);
3113
2344
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3114
2345
 
3115
2346
        mutex_enter(&block->mutex);
3122
2353
        }
3123
2354
 
3124
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);
3125
2358
 
3126
2359
        mutex_exit(&block->mutex);
3127
2360
 
3128
 
        /* Check if this is the first access to the page.
3129
 
        We do a dirty read on purpose, to avoid mutex contention.
3130
 
        This field is only used for heuristic purposes; it does not
3131
 
        affect correctness. */
 
2361
        buf_block_make_young(&block->page);
3132
2362
 
3133
 
        access_time = buf_page_is_accessed(&block->page);
3134
 
        buf_page_set_accessed_make_young(&block->page, access_time);
 
2363
        /* Check if this is the first access to the page */
3135
2364
 
3136
2365
        ut_ad(!ibuf_inside()
3137
2366
              || ibuf_page(buf_block_get_space(block),
3183
2412
#ifdef UNIV_DEBUG_FILE_ACCESSES
3184
2413
        ut_a(block->page.file_page_was_freed == FALSE);
3185
2414
#endif
3186
 
        if (UNIV_UNLIKELY(!access_time)) {
 
2415
        if (UNIV_UNLIKELY(!accessed)) {
3187
2416
                /* In the case of a first access, try to apply linear
3188
2417
                read-ahead */
3189
2418
 
3196
2425
        ut_a(ibuf_count_get(buf_block_get_space(block),
3197
2426
                            buf_block_get_page_no(block)) == 0);
3198
2427
#endif
3199
 
        buf_pool = buf_pool_from_block(block);
3200
 
        buf_pool->stat.n_page_gets++;
 
2428
        buf_pool->n_page_gets++;
3201
2429
 
3202
2430
        return(TRUE);
3203
2431
}
3218
2446
        ulint           line,   /*!< in: line where called */
3219
2447
        mtr_t*          mtr)    /*!< in: mini-transaction */
3220
2448
{
3221
 
        buf_pool_t*     buf_pool;
3222
2449
        ibool           success;
3223
2450
        ulint           fix_type;
3224
2451
 
3225
2452
        ut_ad(mtr);
3226
 
        ut_ad(mtr->state == MTR_ACTIVE);
3227
2453
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3228
2454
 
3229
2455
        mutex_enter(&block->mutex);
3247
2473
 
3248
2474
        mutex_exit(&block->mutex);
3249
2475
 
3250
 
        buf_pool = buf_pool_from_block(block);
3251
 
 
3252
 
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
3253
 
                buf_pool_mutex_enter(buf_pool);
3254
 
                buf_LRU_make_block_young(&block->page);
3255
 
                buf_pool_mutex_exit(buf_pool);
3256
 
        } else if (!buf_page_is_accessed(&block->page)) {
3257
 
                /* Above, we do a dirty read on purpose, to avoid
3258
 
                mutex contention.  The field buf_page_t::access_time
3259
 
                is only used for heuristic purposes.  Writes to the
3260
 
                field must be protected by mutex, however. */
3261
 
                ulint   time_ms = ut_time_ms();
3262
 
 
3263
 
                buf_pool_mutex_enter(buf_pool);
3264
 
                buf_page_set_accessed(&block->page, time_ms);
3265
 
                buf_pool_mutex_exit(buf_pool);
 
2476
        if (mode == BUF_MAKE_YOUNG) {
 
2477
                buf_block_make_young(&block->page);
3266
2478
        }
3267
2479
 
3268
2480
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
3301
2513
             || (ibuf_count_get(buf_block_get_space(block),
3302
2514
                                buf_block_get_page_no(block)) == 0));
3303
2515
#endif
3304
 
        buf_pool->stat.n_page_gets++;
 
2516
        buf_pool->n_page_gets++;
3305
2517
 
3306
2518
        return(TRUE);
3307
2519
}
3324
2536
        buf_block_t*    block;
3325
2537
        ibool           success;
3326
2538
        ulint           fix_type;
3327
 
        buf_pool_t*     buf_pool = buf_pool_get(space_id, page_no);
3328
 
 
3329
 
        ut_ad(mtr);
3330
 
        ut_ad(mtr->state == MTR_ACTIVE);
3331
 
 
3332
 
        buf_pool_mutex_enter(buf_pool);
3333
 
        block = buf_block_hash_get(buf_pool, space_id, page_no);
3334
 
 
3335
 
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
3336
 
                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();
3337
2545
                return(NULL);
3338
2546
        }
3339
2547
 
3340
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
3341
 
 
3342
2548
        mutex_enter(&block->mutex);
3343
 
        buf_pool_mutex_exit(buf_pool);
 
2549
        buf_pool_mutex_exit();
3344
2550
 
3345
2551
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3346
2552
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3383
2589
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3384
2590
        buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
3385
2591
 
3386
 
        buf_pool->stat.n_page_gets++;
 
2592
        buf_pool->n_page_gets++;
3387
2593
 
3388
2594
#ifdef UNIV_IBUF_COUNT_DEBUG
3389
2595
        ut_a(ibuf_count_get(buf_block_get_space(block),
3402
2608
        buf_page_t*     bpage)  /*!< in: block to init */
3403
2609
{
3404
2610
        bpage->flush_type = BUF_FLUSH_LRU;
 
2611
        bpage->accessed = FALSE;
3405
2612
        bpage->io_fix = BUF_IO_NONE;
3406
2613
        bpage->buf_fix_count = 0;
3407
2614
        bpage->freed_page_clock = 0;
3408
 
        bpage->access_time = 0;
3409
2615
        bpage->newest_modification = 0;
3410
2616
        bpage->oldest_modification = 0;
3411
2617
        HASH_INVALIDATE(bpage, hash);
3423
2629
        ulint           space,  /*!< in: space id */
3424
2630
        ulint           offset, /*!< in: offset of the page within space
3425
2631
                                in units of a page */
3426
 
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
3427
2632
        buf_block_t*    block)  /*!< in: block to init */
3428
2633
{
3429
2634
        buf_page_t*     hash_page;
3430
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3431
2635
 
3432
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2636
        ut_ad(buf_pool_mutex_own());
3433
2637
        ut_ad(mutex_own(&(block->mutex)));
3434
2638
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
3435
2639
 
3447
2651
 
3448
2652
        buf_block_init_low(block);
3449
2653
 
3450
 
        block->lock_hash_val = lock_rec_hash(space, offset);
3451
 
 
3452
 
        buf_page_init_low(&block->page);
 
2654
        block->lock_hash_val    = lock_rec_hash(space, offset);
3453
2655
 
3454
2656
        /* Insert into the hash table of file pages */
3455
2657
 
3456
 
        hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
3457
 
 
3458
 
        if (UNIV_LIKELY(!hash_page)) {
3459
 
        } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
3460
 
                /* Preserve the reference count. */
3461
 
                ulint   buf_fix_count = hash_page->buf_fix_count;
3462
 
 
3463
 
                ut_a(buf_fix_count > 0);
3464
 
                block->page.buf_fix_count += buf_fix_count;
3465
 
                buf_pool_watch_remove(buf_pool, fold, hash_page);
3466
 
        } else {
 
2658
        hash_page = buf_page_hash_get(space, offset);
 
2659
 
 
2660
        if (UNIV_LIKELY_NULL(hash_page)) {
3467
2661
                fprintf(stderr,
3468
2662
                        "InnoDB: Error: page %lu %lu already found"
3469
2663
                        " in the hash table: %p, %p\n",
3472
2666
                        (const void*) hash_page, (const void*) block);
3473
2667
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3474
2668
                mutex_exit(&block->mutex);
3475
 
                buf_pool_mutex_exit(buf_pool);
 
2669
                buf_pool_mutex_exit();
3476
2670
                buf_print();
3477
2671
                buf_LRU_print();
3478
2672
                buf_validate();
3481
2675
                ut_error;
3482
2676
        }
3483
2677
 
 
2678
        buf_page_init_low(&block->page);
 
2679
 
3484
2680
        ut_ad(!block->page.in_zip_hash);
3485
2681
        ut_ad(!block->page.in_page_hash);
3486
2682
        ut_d(block->page.in_page_hash = TRUE);
3487
2683
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
3488
 
                    fold, &block->page);
 
2684
                    buf_page_address_fold(space, offset), &block->page);
3489
2685
}
3490
2686
 
3491
2687
/********************************************************************//**
3507
2703
        ulint           space,  /*!< in: space id */
3508
2704
        ulint           zip_size,/*!< in: compressed page size, or 0 */
3509
2705
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
3510
 
        ib_int64_t      tablespace_version,
3511
 
                                /*!< in: prevents reading from a wrong
 
2706
        ib_int64_t      tablespace_version,/*!< in: prevents reading from a wrong
3512
2707
                                version of the tablespace in case we have done
3513
2708
                                DISCARD + IMPORT */
3514
2709
        ulint           offset) /*!< in: page number */
3515
2710
{
3516
2711
        buf_block_t*    block;
3517
 
        buf_page_t*     bpage   = NULL;
3518
 
        buf_page_t*     watch_page;
 
2712
        buf_page_t*     bpage;
3519
2713
        mtr_t           mtr;
3520
 
        ulint           fold;
3521
2714
        ibool           lru     = FALSE;
3522
2715
        void*           data;
3523
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3524
2716
 
3525
2717
        ut_ad(buf_pool);
3526
2718
 
3549
2741
            && UNIV_LIKELY(!recv_recovery_is_on())) {
3550
2742
                block = NULL;
3551
2743
        } else {
3552
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2744
                block = buf_LRU_get_free_block(0);
3553
2745
                ut_ad(block);
3554
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
3555
2746
        }
3556
2747
 
3557
 
        fold = buf_page_address_fold(space, offset);
3558
 
 
3559
 
        buf_pool_mutex_enter(buf_pool);
3560
 
 
3561
 
        watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
3562
 
        if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
 
2748
        buf_pool_mutex_enter();
 
2749
 
 
2750
        if (buf_page_hash_get(space, offset)) {
3563
2751
                /* The page is already in the buffer pool. */
3564
 
                watch_page = NULL;
3565
2752
err_exit:
3566
2753
                if (block) {
3567
2754
                        mutex_enter(&block->mutex);
3585
2772
        if (block) {
3586
2773
                bpage = &block->page;
3587
2774
                mutex_enter(&block->mutex);
3588
 
 
3589
 
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
3590
 
 
3591
 
                buf_page_init(space, offset, fold, block);
 
2775
                buf_page_init(space, offset, block);
3592
2776
 
3593
2777
                /* The block must be put to the LRU list, to the old blocks */
3594
2778
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3608
2792
                if (UNIV_UNLIKELY(zip_size)) {
3609
2793
                        page_zip_set_size(&block->page.zip, zip_size);
3610
2794
 
3611
 
                        /* buf_pool->mutex may be released and
 
2795
                        /* buf_pool_mutex may be released and
3612
2796
                        reacquired by buf_buddy_alloc().  Thus, we
3613
2797
                        must release block->mutex in order not to
3614
2798
                        break the latching order in the reacquisition
3615
 
                        of buf_pool->mutex.  We also must defer this
 
2799
                        of buf_pool_mutex.  We also must defer this
3616
2800
                        operation until after the block descriptor has
3617
2801
                        been added to buf_pool->LRU and
3618
2802
                        buf_pool->page_hash. */
3619
2803
                        mutex_exit(&block->mutex);
3620
 
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2804
                        data = buf_buddy_alloc(zip_size, &lru);
3621
2805
                        mutex_enter(&block->mutex);
3622
2806
                        block->page.zip.data = data;
3623
2807
 
3641
2825
                control block (bpage), in order to avoid the
3642
2826
                invocation of buf_buddy_relocate_block() on
3643
2827
                uninitialized data. */
3644
 
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3645
 
                bpage = buf_buddy_alloc(buf_pool, sizeof *bpage, &lru);
3646
 
 
3647
 
                /* Initialize the buf_pool pointer. */
3648
 
                bpage->buf_pool = buf_pool;
 
2828
                data = buf_buddy_alloc(zip_size, &lru);
 
2829
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3649
2830
 
3650
2831
                /* If buf_buddy_alloc() allocated storage from the LRU list,
3651
 
                it released and reacquired buf_pool->mutex.  Thus, we must
 
2832
                it released and reacquired buf_pool_mutex.  Thus, we must
3652
2833
                check the page_hash again, as it may have been modified. */
3653
 
                if (UNIV_UNLIKELY(lru)) {
3654
 
 
3655
 
                        watch_page = buf_page_hash_get_low(
3656
 
                                buf_pool, space, offset, fold);
3657
 
 
3658
 
                        if (watch_page
3659
 
                            && !buf_pool_watch_is_sentinel(buf_pool,
3660
 
                                                           watch_page)) {
3661
 
 
3662
 
                                /* The block was added by some other thread. */
3663
 
                                watch_page = NULL;
3664
 
                                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
3665
 
                                buf_buddy_free(buf_pool, data, zip_size);
3666
 
 
3667
 
                                bpage = NULL;
3668
 
                                goto func_exit;
3669
 
                        }
 
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;
3670
2843
                }
3671
2844
 
3672
2845
                page_zip_des_init(&bpage->zip);
3673
2846
                page_zip_set_size(&bpage->zip, zip_size);
3674
2847
                bpage->zip.data = data;
3675
2848
 
3676
 
                mutex_enter(&buf_pool->zip_mutex);
 
2849
                mutex_enter(&buf_pool_zip_mutex);
3677
2850
                UNIV_MEM_DESC(bpage->zip.data,
3678
2851
                              page_zip_get_size(&bpage->zip), bpage);
3679
 
 
3680
2852
                buf_page_init_low(bpage);
3681
 
 
3682
2853
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
3683
2854
                bpage->space    = space;
3684
2855
                bpage->offset   = offset;
3685
2856
 
3686
 
 
3687
2857
#ifdef UNIV_DEBUG
3688
2858
                bpage->in_page_hash = FALSE;
3689
2859
                bpage->in_zip_hash = FALSE;
3693
2863
#endif /* UNIV_DEBUG */
3694
2864
 
3695
2865
                ut_d(bpage->in_page_hash = TRUE);
3696
 
 
3697
 
                if (UNIV_LIKELY_NULL(watch_page)) {
3698
 
                        /* Preserve the reference count. */
3699
 
                        ulint   buf_fix_count = watch_page->buf_fix_count;
3700
 
                        ut_a(buf_fix_count > 0);
3701
 
                        bpage->buf_fix_count += buf_fix_count;
3702
 
                        ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
3703
 
                        buf_pool_watch_remove(buf_pool, fold, watch_page);
3704
 
                }
3705
 
 
3706
 
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
3707
 
                            bpage);
 
2866
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
2867
                            buf_page_address_fold(space, offset), bpage);
3708
2868
 
3709
2869
                /* The block must be put to the LRU list, to the old blocks */
3710
2870
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3712
2872
 
3713
2873
                buf_page_set_io_fix(bpage, BUF_IO_READ);
3714
2874
 
3715
 
                mutex_exit(&buf_pool->zip_mutex);
 
2875
                mutex_exit(&buf_pool_zip_mutex);
3716
2876
        }
3717
2877
 
3718
2878
        buf_pool->n_pend_reads++;
3719
2879
func_exit:
3720
 
        buf_pool_mutex_exit(buf_pool);
 
2880
        buf_pool_mutex_exit();
3721
2881
 
3722
2882
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
3723
2883
 
3746
2906
{
3747
2907
        buf_frame_t*    frame;
3748
2908
        buf_block_t*    block;
3749
 
        ulint           fold;
3750
2909
        buf_block_t*    free_block      = NULL;
3751
 
        ulint           time_ms         = ut_time_ms();
3752
 
        buf_pool_t*     buf_pool        = buf_pool_get(space, offset);
3753
2910
 
3754
2911
        ut_ad(mtr);
3755
 
        ut_ad(mtr->state == MTR_ACTIVE);
3756
2912
        ut_ad(space || !zip_size);
3757
2913
 
3758
 
        free_block = buf_LRU_get_free_block(buf_pool, 0);
3759
 
 
3760
 
        fold = buf_page_address_fold(space, offset);
3761
 
 
3762
 
        buf_pool_mutex_enter(buf_pool);
3763
 
 
3764
 
        block = (buf_block_t*) buf_page_hash_get_low(
3765
 
                buf_pool, space, offset, fold);
3766
 
 
3767
 
        if (block
3768
 
            && buf_page_in_file(&block->page)
3769
 
            && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
 
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)) {
3770
2921
#ifdef UNIV_IBUF_COUNT_DEBUG
3771
2922
                ut_a(ibuf_count_get(space, offset) == 0);
3772
2923
#endif
3775
2926
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3776
2927
 
3777
2928
                /* Page can be found in buf_pool */
3778
 
                buf_pool_mutex_exit(buf_pool);
 
2929
                buf_pool_mutex_exit();
3779
2930
 
3780
2931
                buf_block_free(free_block);
3781
2932
 
3796
2947
 
3797
2948
        mutex_enter(&block->mutex);
3798
2949
 
3799
 
        buf_page_init(space, offset, fold, block);
 
2950
        buf_page_init(space, offset, block);
3800
2951
 
3801
2952
        /* The block must be put to the LRU list */
3802
2953
        buf_LRU_add_block(&block->page, FALSE);
3803
2954
 
3804
2955
        buf_block_buf_fix_inc(block, __FILE__, __LINE__);
3805
 
        buf_pool->stat.n_pages_created++;
 
2956
        buf_pool->n_pages_created++;
3806
2957
 
3807
2958
        if (zip_size) {
3808
2959
                void*   data;
3809
2960
                ibool   lru;
3810
2961
 
3811
2962
                /* Prevent race conditions during buf_buddy_alloc(),
3812
 
                which may release and reacquire buf_pool->mutex,
 
2963
                which may release and reacquire buf_pool_mutex,
3813
2964
                by IO-fixing and X-latching the block. */
3814
2965
 
3815
2966
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3817
2968
 
3818
2969
                page_zip_set_size(&block->page.zip, zip_size);
3819
2970
                mutex_exit(&block->mutex);
3820
 
                /* buf_pool->mutex may be released and reacquired by
 
2971
                /* buf_pool_mutex may be released and reacquired by
3821
2972
                buf_buddy_alloc().  Thus, we must release block->mutex
3822
2973
                in order not to break the latching order in
3823
 
                the reacquisition of buf_pool->mutex.  We also must
 
2974
                the reacquisition of buf_pool_mutex.  We also must
3824
2975
                defer this operation until after the block descriptor
3825
2976
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3826
 
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2977
                data = buf_buddy_alloc(zip_size, &lru);
3827
2978
                mutex_enter(&block->mutex);
3828
2979
                block->page.zip.data = data;
3829
2980
 
3839
2990
                rw_lock_x_unlock(&block->lock);
3840
2991
        }
3841
2992
 
3842
 
        buf_page_set_accessed(&block->page, time_ms);
3843
 
 
3844
 
        buf_pool_mutex_exit(buf_pool);
 
2993
        buf_pool_mutex_exit();
3845
2994
 
3846
2995
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3847
2996
 
 
2997
        buf_page_set_accessed(&block->page, TRUE);
 
2998
 
3848
2999
        mutex_exit(&block->mutex);
3849
3000
 
3850
3001
        /* Delete possible entries for the page from the insert buffer:
3853
3004
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3854
3005
 
3855
3006
        /* Flush pages from the end of the LRU list if necessary */
3856
 
        buf_flush_free_margin(buf_pool);
 
3007
        buf_flush_free_margin();
3857
3008
 
3858
3009
        frame = block->frame;
3859
3010
 
3889
3040
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
3890
3041
{
3891
3042
        enum buf_io_fix io_type;
3892
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3893
3043
        const ibool     uncompressed = (buf_page_get_state(bpage)
3894
3044
                                        == BUF_BLOCK_FILE_PAGE);
3895
3045
 
4025
3175
                }
4026
3176
        }
4027
3177
 
4028
 
        buf_pool_mutex_enter(buf_pool);
 
3178
        buf_pool_mutex_enter();
4029
3179
        mutex_enter(buf_page_get_mutex(bpage));
4030
3180
 
4031
3181
#ifdef UNIV_IBUF_COUNT_DEBUG
4051
3201
 
4052
3202
                ut_ad(buf_pool->n_pend_reads > 0);
4053
3203
                buf_pool->n_pend_reads--;
4054
 
                buf_pool->stat.n_pages_read++;
 
3204
                buf_pool->n_pages_read++;
4055
3205
 
4056
3206
                if (uncompressed) {
4057
3207
                        rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock,
4071
3221
                                             BUF_IO_WRITE);
4072
3222
                }
4073
3223
 
4074
 
                buf_pool->stat.n_pages_written++;
 
3224
                buf_pool->n_pages_written++;
4075
3225
 
4076
3226
                break;
4077
3227
 
4089
3239
#endif /* UNIV_DEBUG */
4090
3240
 
4091
3241
        mutex_exit(buf_page_get_mutex(bpage));
4092
 
        buf_pool_mutex_exit(buf_pool);
4093
 
}
4094
 
 
4095
 
/*********************************************************************//**
4096
 
Asserts that all file pages in the buffer are in a replaceable state.
4097
 
@return TRUE */
4098
 
static
4099
 
ibool
4100
 
buf_all_freed_instance(
4101
 
/*===================*/
4102
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instancce */
4103
 
{
4104
 
        ulint           i;
4105
 
        buf_chunk_t*    chunk;
4106
 
 
4107
 
        ut_ad(buf_pool);
4108
 
 
4109
 
        buf_pool_mutex_enter(buf_pool);
4110
 
 
4111
 
        chunk = buf_pool->chunks;
4112
 
 
4113
 
        for (i = buf_pool->n_chunks; i--; chunk++) {
4114
 
 
4115
 
                const buf_block_t* block = buf_chunk_not_freed(chunk);
4116
 
 
4117
 
                if (UNIV_LIKELY_NULL(block)) {
4118
 
                        fprintf(stderr,
4119
 
                                "Page %lu %lu still fixed or dirty\n",
4120
 
                                (ulong) block->page.space,
4121
 
                                (ulong) block->page.offset);
4122
 
                        ut_error;
4123
 
                }
4124
 
        }
4125
 
 
4126
 
        buf_pool_mutex_exit(buf_pool);
4127
 
 
4128
 
        return(TRUE);
4129
 
}
4130
 
 
4131
 
/*********************************************************************//**
4132
 
Invalidates file pages in one buffer pool instance */
4133
 
static
 
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
4134
3250
void
4135
 
buf_pool_invalidate_instance(
4136
 
/*=========================*/
4137
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3251
buf_pool_invalidate(void)
 
3252
/*=====================*/
4138
3253
{
4139
 
        ibool           freed;
4140
 
        enum buf_flush  i;
4141
 
 
4142
 
        buf_pool_mutex_enter(buf_pool);
4143
 
 
4144
 
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
4145
 
 
4146
 
                /* As this function is called during startup and
4147
 
                during redo application phase during recovery, InnoDB
4148
 
                is single threaded (apart from IO helper threads) at
4149
 
                this stage. No new write batch can be in intialization
4150
 
                stage at this point. */
4151
 
                ut_ad(buf_pool->init_flush[i] == FALSE);
4152
 
 
4153
 
                /* However, it is possible that a write batch that has
4154
 
                been posted earlier is still not complete. For buffer
4155
 
                pool invalidation to proceed we must ensure there is NO
4156
 
                write activity happening. */
4157
 
                if (buf_pool->n_flush[i] > 0) {
4158
 
                        buf_pool_mutex_exit(buf_pool);
4159
 
                        buf_flush_wait_batch_end(buf_pool, i);
4160
 
                        buf_pool_mutex_enter(buf_pool);
4161
 
                }
4162
 
        }
4163
 
 
4164
 
        buf_pool_mutex_exit(buf_pool);
4165
 
 
4166
 
        ut_ad(buf_all_freed_instance(buf_pool));
 
3254
        ibool   freed;
 
3255
 
 
3256
        ut_ad(buf_all_freed());
4167
3257
 
4168
3258
        freed = TRUE;
4169
3259
 
4170
3260
        while (freed) {
4171
 
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
 
3261
                freed = buf_LRU_search_and_free_block(100);
4172
3262
        }
4173
3263
 
4174
 
        buf_pool_mutex_enter(buf_pool);
 
3264
        buf_pool_mutex_enter();
4175
3265
 
4176
3266
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
4177
3267
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
4178
3268
 
4179
 
        buf_pool->freed_page_clock = 0;
4180
 
        buf_pool->LRU_old = NULL;
4181
 
        buf_pool->LRU_old_len = 0;
4182
 
        buf_pool->LRU_flush_ended = 0;
4183
 
 
4184
 
        memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
4185
 
        buf_refresh_io_stats(buf_pool);
4186
 
 
4187
 
        buf_pool_mutex_exit(buf_pool);
4188
 
}
4189
 
 
4190
 
/*********************************************************************//**
4191
 
Invalidates the file pages in the buffer pool when an archive recovery is
4192
 
completed. All the file pages buffered must be in a replaceable state when
4193
 
this function is called: not latched and not modified. */
4194
 
UNIV_INTERN
4195
 
void
4196
 
buf_pool_invalidate(void)
4197
 
/*=====================*/
4198
 
{
4199
 
        ulint   i;
4200
 
 
4201
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4202
 
                buf_pool_invalidate_instance(buf_pool_from_array(i));
4203
 
        }
 
3269
        buf_pool_mutex_exit();
4204
3270
}
4205
3271
 
4206
3272
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4207
3273
/*********************************************************************//**
4208
 
Validates data in one buffer pool instance
 
3274
Validates the buffer buf_pool data structure.
4209
3275
@return TRUE */
4210
 
static
 
3276
UNIV_INTERN
4211
3277
ibool
4212
 
buf_pool_validate_instance(
4213
 
/*=======================*/
4214
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3278
buf_validate(void)
 
3279
/*==============*/
4215
3280
{
4216
3281
        buf_page_t*     b;
4217
3282
        buf_chunk_t*    chunk;
4226
3291
 
4227
3292
        ut_ad(buf_pool);
4228
3293
 
4229
 
        buf_pool_mutex_enter(buf_pool);
 
3294
        buf_pool_mutex_enter();
4230
3295
 
4231
3296
        chunk = buf_pool->chunks;
4232
3297
 
4251
3316
                                break;
4252
3317
 
4253
3318
                        case BUF_BLOCK_FILE_PAGE:
4254
 
                                ut_a(buf_page_hash_get(buf_pool,
4255
 
                                                       buf_block_get_space(
 
3319
                                ut_a(buf_page_hash_get(buf_block_get_space(
4256
3320
                                                               block),
4257
3321
                                                       buf_block_get_page_no(
4258
3322
                                                               block))
4299
3363
                                }
4300
3364
 
4301
3365
                                n_lru++;
 
3366
 
 
3367
                                if (block->page.oldest_modification > 0) {
 
3368
                                        n_flush++;
 
3369
                                }
 
3370
 
4302
3371
                                break;
4303
3372
 
4304
3373
                        case BUF_BLOCK_NOT_USED:
4316
3385
                }
4317
3386
        }
4318
3387
 
4319
 
        mutex_enter(&buf_pool->zip_mutex);
 
3388
        mutex_enter(&buf_pool_zip_mutex);
4320
3389
 
4321
3390
        /* Check clean compressed-only blocks. */
4322
3391
 
4337
3406
                        ut_error;
4338
3407
                        break;
4339
3408
                }
4340
 
 
4341
 
                /* It is OK to read oldest_modification here because
4342
 
                we have acquired buf_pool->zip_mutex above which acts
4343
 
                as the 'block->mutex' for these bpages. */
4344
3409
                ut_a(!b->oldest_modification);
4345
 
                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);
4346
3411
 
4347
3412
                n_lru++;
4348
3413
                n_zip++;
4349
3414
        }
4350
3415
 
4351
 
        /* Check dirty blocks. */
 
3416
        /* Check dirty compressed-only blocks. */
4352
3417
 
4353
 
        buf_flush_list_mutex_enter(buf_pool);
4354
3418
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4355
3419
             b = UT_LIST_GET_NEXT(list, b)) {
4356
3420
                ut_ad(b->in_flush_list);
4357
 
                ut_a(b->oldest_modification);
4358
 
                n_flush++;
4359
3421
 
4360
3422
                switch (buf_page_get_state(b)) {
4361
3423
                case BUF_BLOCK_ZIP_DIRTY:
 
3424
                        ut_a(b->oldest_modification);
4362
3425
                        n_lru++;
 
3426
                        n_flush++;
4363
3427
                        n_zip++;
4364
3428
                        switch (buf_page_get_io_fix(b)) {
4365
3429
                        case BUF_IO_NONE:
4366
3430
                        case BUF_IO_READ:
4367
3431
                                break;
 
3432
 
4368
3433
                        case BUF_IO_WRITE:
4369
3434
                                switch (buf_page_get_flush_type(b)) {
4370
3435
                                case BUF_FLUSH_LRU:
4394
3459
                        ut_error;
4395
3460
                        break;
4396
3461
                }
4397
 
                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);
4398
3463
        }
4399
3464
 
4400
 
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4401
 
 
4402
 
        buf_flush_list_mutex_exit(buf_pool);
4403
 
 
4404
 
        mutex_exit(&buf_pool->zip_mutex);
 
3465
        mutex_exit(&buf_pool_zip_mutex);
4405
3466
 
4406
3467
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
4407
3468
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
4417
3478
                        (ulong) n_free);
4418
3479
                ut_error;
4419
3480
        }
 
3481
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4420
3482
 
4421
3483
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
4422
3484
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
4423
3485
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
4424
3486
 
4425
 
        buf_pool_mutex_exit(buf_pool);
 
3487
        buf_pool_mutex_exit();
4426
3488
 
4427
3489
        ut_a(buf_LRU_validate());
4428
 
        ut_a(buf_flush_validate(buf_pool));
4429
 
 
4430
 
        return(TRUE);
4431
 
}
4432
 
 
4433
 
/*********************************************************************//**
4434
 
Validates the buffer buf_pool data structure.
4435
 
@return TRUE */
4436
 
UNIV_INTERN
4437
 
ibool
4438
 
buf_validate(void)
4439
 
/*==============*/
4440
 
{
4441
 
        ulint   i;
4442
 
 
4443
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4444
 
                buf_pool_t*     buf_pool;
4445
 
 
4446
 
                buf_pool = buf_pool_from_array(i);
4447
 
 
4448
 
                buf_pool_validate_instance(buf_pool);
4449
 
        }
4450
 
        return(TRUE);
4451
 
}
4452
 
 
 
3490
        ut_a(buf_flush_validate());
 
3491
 
 
3492
        return(TRUE);
 
3493
}
4453
3494
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
4454
3495
 
4455
3496
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4456
3497
/*********************************************************************//**
4457
 
Prints info of the buffer buf_pool data structure for one instance. */
4458
 
static
 
3498
Prints info of the buffer buf_pool data structure. */
 
3499
UNIV_INTERN
4459
3500
void
4460
 
buf_print_instance(
4461
 
/*===============*/
4462
 
        buf_pool_t*     buf_pool)
 
3501
buf_print(void)
 
3502
/*===========*/
4463
3503
{
4464
 
        index_id_t*     index_ids;
 
3504
        dulint*         index_ids;
4465
3505
        ulint*          counts;
4466
3506
        ulint           size;
4467
3507
        ulint           i;
4468
3508
        ulint           j;
4469
 
        index_id_t      id;
 
3509
        dulint          id;
4470
3510
        ulint           n_found;
4471
3511
        buf_chunk_t*    chunk;
4472
3512
        dict_index_t*   index;
4475
3515
 
4476
3516
        size = buf_pool->curr_size;
4477
3517
 
4478
 
        index_ids = mem_alloc(size * sizeof *index_ids);
 
3518
        index_ids = mem_alloc(sizeof(dulint) * size);
4479
3519
        counts = mem_alloc(sizeof(ulint) * size);
4480
3520
 
4481
 
        buf_pool_mutex_enter(buf_pool);
4482
 
        buf_flush_list_mutex_enter(buf_pool);
 
3521
        buf_pool_mutex_enter();
4483
3522
 
4484
3523
        fprintf(stderr,
4485
3524
                "buf_pool size %lu\n"
4489
3528
                "n pending decompressions %lu\n"
4490
3529
                "n pending reads %lu\n"
4491
3530
                "n pending flush LRU %lu list %lu single page %lu\n"
4492
 
                "pages made young %lu, not young %lu\n"
4493
3531
                "pages read %lu, created %lu, written %lu\n",
4494
3532
                (ulong) size,
4495
3533
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4500
3538
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU],
4501
3539
                (ulong) buf_pool->n_flush[BUF_FLUSH_LIST],
4502
3540
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE],
4503
 
                (ulong) buf_pool->stat.n_pages_made_young,
4504
 
                (ulong) buf_pool->stat.n_pages_not_made_young,
4505
 
                (ulong) buf_pool->stat.n_pages_read,
4506
 
                (ulong) buf_pool->stat.n_pages_created,
4507
 
                (ulong) buf_pool->stat.n_pages_written);
4508
 
 
4509
 
        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);
4510
3543
 
4511
3544
        /* Count the number of blocks belonging to each index in the buffer */
4512
3545
 
4530
3563
 
4531
3564
                                while (j < n_found) {
4532
3565
 
4533
 
                                        if (index_ids[j] == id) {
 
3566
                                        if (ut_dulint_cmp(index_ids[j],
 
3567
                                                          id) == 0) {
4534
3568
                                                counts[j]++;
4535
3569
 
4536
3570
                                                break;
4547
3581
                }
4548
3582
        }
4549
3583
 
4550
 
        buf_pool_mutex_exit(buf_pool);
 
3584
        buf_pool_mutex_exit();
4551
3585
 
4552
3586
        for (i = 0; i < n_found; i++) {
4553
3587
                index = dict_index_get_if_in_cache(index_ids[i]);
4554
3588
 
4555
3589
                fprintf(stderr,
4556
 
                        "Block count for index %llu in buffer is about %lu",
4557
 
                        (ullint) index_ids[i],
 
3590
                        "Block count for index %lu in buffer is about %lu",
 
3591
                        (ulong) ut_dulint_get_low(index_ids[i]),
4558
3592
                        (ulong) counts[i]);
4559
3593
 
4560
3594
                if (index) {
4568
3602
        mem_free(index_ids);
4569
3603
        mem_free(counts);
4570
3604
 
4571
 
        ut_a(buf_pool_validate_instance(buf_pool));
4572
 
}
4573
 
 
4574
 
/*********************************************************************//**
4575
 
Prints info of the buffer buf_pool data structure. */
4576
 
UNIV_INTERN
4577
 
void
4578
 
buf_print(void)
4579
 
/*===========*/
4580
 
{
4581
 
        ulint   i;
4582
 
 
4583
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4584
 
                buf_pool_t*     buf_pool;
4585
 
 
4586
 
                buf_pool = buf_pool_from_array(i);
4587
 
                buf_print_instance(buf_pool);
4588
 
        }
 
3605
        ut_a(buf_validate());
4589
3606
}
4590
3607
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
4591
3608
 
4595
3612
@return number of latched pages */
4596
3613
UNIV_INTERN
4597
3614
ulint
4598
 
buf_get_latched_pages_number_instance(
4599
 
/*==================================*/
4600
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3615
buf_get_latched_pages_number(void)
 
3616
/*==============================*/
4601
3617
{
 
3618
        buf_chunk_t*    chunk;
4602
3619
        buf_page_t*     b;
4603
3620
        ulint           i;
4604
 
        buf_chunk_t*    chunk;
4605
3621
        ulint           fixed_pages_number = 0;
4606
3622
 
4607
 
        buf_pool_mutex_enter(buf_pool);
 
3623
        buf_pool_mutex_enter();
4608
3624
 
4609
3625
        chunk = buf_pool->chunks;
4610
3626
 
4633
3649
                }
4634
3650
        }
4635
3651
 
4636
 
        mutex_enter(&buf_pool->zip_mutex);
 
3652
        mutex_enter(&buf_pool_zip_mutex);
4637
3653
 
4638
3654
        /* Traverse the lists of clean and dirty compressed-only blocks. */
4639
3655
 
4648
3664
                }
4649
3665
        }
4650
3666
 
4651
 
        buf_flush_list_mutex_enter(buf_pool);
4652
3667
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4653
3668
             b = UT_LIST_GET_NEXT(list, b)) {
4654
3669
                ut_ad(b->in_flush_list);
4674
3689
                }
4675
3690
        }
4676
3691
 
4677
 
        buf_flush_list_mutex_exit(buf_pool);
4678
 
        mutex_exit(&buf_pool->zip_mutex);
4679
 
        buf_pool_mutex_exit(buf_pool);
 
3692
        mutex_exit(&buf_pool_zip_mutex);
 
3693
        buf_pool_mutex_exit();
4680
3694
 
4681
3695
        return(fixed_pages_number);
4682
3696
}
4683
 
 
4684
 
/*********************************************************************//**
4685
 
Returns the number of latched pages in all the buffer pools.
4686
 
@return number of latched pages */
4687
 
UNIV_INTERN
4688
 
ulint
4689
 
buf_get_latched_pages_number(void)
4690
 
/*==============================*/
4691
 
{
4692
 
        ulint   i;
4693
 
        ulint   total_latched_pages = 0;
4694
 
 
4695
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4696
 
                buf_pool_t*     buf_pool;
4697
 
 
4698
 
                buf_pool = buf_pool_from_array(i);
4699
 
 
4700
 
                total_latched_pages += buf_get_latched_pages_number_instance(
4701
 
                        buf_pool);
4702
 
        }
4703
 
 
4704
 
        return(total_latched_pages);
4705
 
}
4706
 
 
4707
3697
#endif /* UNIV_DEBUG */
4708
3698
 
4709
3699
/*********************************************************************//**
4714
3704
buf_get_n_pending_ios(void)
4715
3705
/*=======================*/
4716
3706
{
4717
 
        ulint   i;
4718
 
        ulint   pend_ios = 0;
4719
 
 
4720
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4721
 
                buf_pool_t*     buf_pool;
4722
 
 
4723
 
                buf_pool = buf_pool_from_array(i);
4724
 
 
4725
 
                pend_ios +=
4726
 
                        buf_pool->n_pend_reads
4727
 
                        + buf_pool->n_flush[BUF_FLUSH_LRU]
4728
 
                        + buf_pool->n_flush[BUF_FLUSH_LIST]
4729
 
                        + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
4730
 
        }
4731
 
 
4732
 
        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]);
4733
3711
}
4734
3712
 
4735
3713
/*********************************************************************//**
4741
3719
buf_get_modified_ratio_pct(void)
4742
3720
/*============================*/
4743
3721
{
4744
 
        ulint           ratio;
4745
 
        ulint           lru_len = 0;
4746
 
        ulint           free_len = 0;
4747
 
        ulint           flush_list_len = 0;
4748
 
 
4749
 
        buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
4750
 
 
4751
 
        ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
4752
 
  
 
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
 
4753
3730
        /* 1 + is there to avoid division by zero */
4754
3731
 
 
3732
        buf_pool_mutex_exit();
 
3733
 
4755
3734
        return(ratio);
4756
3735
}
4757
3736
 
4758
3737
/*********************************************************************//**
4759
3738
Prints info of the buffer i/o. */
4760
 
static
 
3739
UNIV_INTERN
4761
3740
void
4762
 
buf_print_io_instance(
4763
 
/*==================*/
4764
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
4765
 
        FILE*           file)           /*!< in/out: buffer where to print */
 
3741
buf_print_io(
 
3742
/*=========*/
 
3743
        FILE*   file)   /*!< in/out: buffer where to print */
4766
3744
{
4767
3745
        time_t  current_time;
4768
3746
        double  time_elapsed;
4769
 
        ulint   n_gets_diff;
 
3747
        ulint   size;
4770
3748
 
4771
3749
        ut_ad(buf_pool);
 
3750
        size = buf_pool->curr_size;
4772
3751
 
4773
 
        buf_pool_mutex_enter(buf_pool);
4774
 
        buf_flush_list_mutex_enter(buf_pool);
 
3752
        buf_pool_mutex_enter();
4775
3753
 
4776
3754
        fprintf(file,
4777
3755
                "Buffer pool size   %lu\n"
4778
3756
                "Free buffers       %lu\n"
4779
3757
                "Database pages     %lu\n"
4780
 
                "Old database pages %lu\n"
4781
3758
                "Modified db pages  %lu\n"
4782
3759
                "Pending reads %lu\n"
4783
3760
                "Pending writes: LRU %lu, flush list %lu, single page %lu\n",
4784
 
                (ulong) buf_pool->curr_size,
 
3761
                (ulong) size,
4785
3762
                (ulong) UT_LIST_GET_LEN(buf_pool->free),
4786
3763
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4787
 
                (ulong) buf_pool->LRU_old_len,
4788
3764
                (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
4789
3765
                (ulong) buf_pool->n_pend_reads,
4790
3766
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
4793
3769
                + buf_pool->init_flush[BUF_FLUSH_LIST],
4794
3770
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4795
3771
 
4796
 
        buf_flush_list_mutex_exit(buf_pool);
4797
 
 
4798
3772
        current_time = time(NULL);
4799
3773
        time_elapsed = 0.001 + difftime(current_time,
4800
3774
                                        buf_pool->last_printout_time);
 
3775
        buf_pool->last_printout_time = current_time;
4801
3776
 
4802
3777
        fprintf(file,
4803
 
                "Pages made young %lu, not young %lu\n"
4804
 
                "%.2f youngs/s, %.2f non-youngs/s\n"
4805
3778
                "Pages read %lu, created %lu, written %lu\n"
4806
3779
                "%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
4807
 
                (ulong) buf_pool->stat.n_pages_made_young,
4808
 
                (ulong) buf_pool->stat.n_pages_not_made_young,
4809
 
                (buf_pool->stat.n_pages_made_young
4810
 
                 - buf_pool->old_stat.n_pages_made_young)
4811
 
                / time_elapsed,
4812
 
                (buf_pool->stat.n_pages_not_made_young
4813
 
                 - buf_pool->old_stat.n_pages_not_made_young)
4814
 
                / time_elapsed,
4815
 
                (ulong) buf_pool->stat.n_pages_read,
4816
 
                (ulong) buf_pool->stat.n_pages_created,
4817
 
                (ulong) buf_pool->stat.n_pages_written,
4818
 
                (buf_pool->stat.n_pages_read
4819
 
                 - buf_pool->old_stat.n_pages_read)
4820
 
                / time_elapsed,
4821
 
                (buf_pool->stat.n_pages_created
4822
 
                 - buf_pool->old_stat.n_pages_created)
4823
 
                / time_elapsed,
4824
 
                (buf_pool->stat.n_pages_written
4825
 
                 - 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)
4826
3788
                / time_elapsed);
4827
3789
 
4828
 
        n_gets_diff = buf_pool->stat.n_page_gets
4829
 
                    - buf_pool->old_stat.n_page_gets;
4830
 
 
4831
 
        if (n_gets_diff) {
4832
 
                fprintf(file,
4833
 
                        "Buffer pool hit rate %lu / 1000,"
4834
 
                        " young-making rate %lu / 1000 not %lu / 1000\n",
4835
 
                        (ulong)
4836
 
                        (1000 - ((1000 * (buf_pool->stat.n_pages_read
4837
 
                                          - buf_pool->old_stat.n_pages_read))
4838
 
                                 / (buf_pool->stat.n_page_gets
4839
 
                                    - buf_pool->old_stat.n_page_gets))),
4840
 
                        (ulong)
4841
 
                        (1000 * (buf_pool->stat.n_pages_made_young
4842
 
                                 - buf_pool->old_stat.n_pages_made_young)
4843
 
                         / n_gets_diff),
4844
 
                        (ulong)
4845
 
                        (1000 * (buf_pool->stat.n_pages_not_made_young
4846
 
                                 - buf_pool->old_stat.n_pages_not_made_young)
4847
 
                         / 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))));
4848
3797
        } else {
4849
3798
                fputs("No buffer pool page gets since the last printout\n",
4850
3799
                      file);
4851
3800
        }
4852
3801
 
4853
 
        /* Statistics about read ahead algorithm */
4854
 
        fprintf(file, "Pages read ahead %.2f/s,"
4855
 
                " evicted without access %.2f/s\n",
4856
 
                (buf_pool->stat.n_ra_pages_read
4857
 
                - buf_pool->old_stat.n_ra_pages_read)
4858
 
                / time_elapsed,
4859
 
                (buf_pool->stat.n_ra_pages_evicted
4860
 
                - buf_pool->old_stat.n_ra_pages_evicted)
4861
 
                / 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;
4862
3806
 
4863
3807
        /* Print some values to help us with visualizing what is
4864
3808
        happening with LRU eviction. */
4870
3814
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
4871
3815
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
4872
3816
 
4873
 
        buf_refresh_io_stats(buf_pool);
4874
 
        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;
4875
3832
}
4876
3833
 
4877
3834
/*********************************************************************//**
4878
 
Prints info of the buffer i/o. */
4879
 
UNIV_INTERN
4880
 
void
4881
 
buf_print_io(
4882
 
/*=========*/
4883
 
        FILE*   file)   /*!< in/out: buffer where to print */
4884
 
{
4885
 
        ulint   i;
4886
 
 
4887
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4888
 
                buf_pool_t*     buf_pool;
4889
 
 
4890
 
                buf_pool = buf_pool_from_array(i);
4891
 
                buf_print_io_instance(buf_pool, file);
4892
 
        }
4893
 
}
4894
 
 
4895
 
/**********************************************************************//**
4896
 
Refreshes the statistics used to print per-second averages. */
4897
 
UNIV_INTERN
4898
 
void
4899
 
buf_refresh_io_stats(
4900
 
/*=================*/
4901
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
4902
 
{
4903
 
        buf_pool->last_printout_time = ut_time();
4904
 
        buf_pool->old_stat = buf_pool->stat;
4905
 
}
4906
 
 
4907
 
/**********************************************************************//**
4908
 
Refreshes the statistics used to print per-second averages. */
4909
 
UNIV_INTERN
4910
 
void
4911
 
buf_refresh_io_stats_all(void)
4912
 
/*==========================*/
4913
 
{
4914
 
        ulint           i;
4915
 
 
4916
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4917
 
                buf_pool_t*     buf_pool;
4918
 
 
4919
 
                buf_pool = buf_pool_from_array(i);
4920
 
 
4921
 
                buf_refresh_io_stats(buf_pool);
4922
 
        }
4923
 
}
4924
 
 
4925
 
/**********************************************************************//**
4926
 
Check if all pages in all buffer pools are in a replacable state.
4927
 
@return FALSE if not */
 
3835
Asserts that all file pages in the buffer are in a replaceable state.
 
3836
@return TRUE */
4928
3837
UNIV_INTERN
4929
3838
ibool
4930
3839
buf_all_freed(void)
4931
3840
/*===============*/
4932
3841
{
4933
 
        ulint   i;
4934
 
 
4935
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4936
 
                buf_pool_t*     buf_pool;
4937
 
 
4938
 
                buf_pool = buf_pool_from_array(i);
4939
 
 
4940
 
                if (!buf_all_freed_instance(buf_pool)) {
4941
 
                        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;
4942
3861
                }
4943
 
        }
 
3862
        }
 
3863
 
 
3864
        buf_pool_mutex_exit();
4944
3865
 
4945
3866
        return(TRUE);
4946
3867
}
4947
 
  
 
3868
 
4948
3869
/*********************************************************************//**
4949
3870
Checks that there currently are no pending i/o-operations for the buffer
4950
3871
pool.
4954
3875
buf_pool_check_no_pending_io(void)
4955
3876
/*==============================*/
4956
3877
{
4957
 
        ulint           i;
4958
 
        ibool           ret = TRUE;
4959
 
 
4960
 
        buf_pool_mutex_enter_all();
4961
 
 
4962
 
        for (i = 0; i < srv_buf_pool_instances && ret; i++) {
4963
 
                const buf_pool_t*       buf_pool;
4964
 
 
4965
 
                buf_pool = buf_pool_from_array(i);
4966
 
 
4967
 
                if (buf_pool->n_pend_reads
4968
 
                    + buf_pool->n_flush[BUF_FLUSH_LRU]
4969
 
                    + buf_pool->n_flush[BUF_FLUSH_LIST]
4970
 
                    + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
4971
 
 
4972
 
                        ret = FALSE;
4973
 
                }
 
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;
4974
3888
        }
4975
3889
 
4976
 
        buf_pool_mutex_exit_all();
 
3890
        buf_pool_mutex_exit();
4977
3891
 
4978
3892
        return(ret);
4979
3893
}
4980
3894
 
4981
 
#if 0
4982
 
Code currently not used
4983
3895
/*********************************************************************//**
4984
3896
Gets the current length of the free list of buffer blocks.
4985
3897
@return length of the free list */
4990
3902
{
4991
3903
        ulint   len;
4992
3904
 
4993
 
        buf_pool_mutex_enter(buf_pool);
 
3905
        buf_pool_mutex_enter();
4994
3906
 
4995
3907
        len = UT_LIST_GET_LEN(buf_pool->free);
4996
3908
 
4997
 
        buf_pool_mutex_exit(buf_pool);
 
3909
        buf_pool_mutex_exit();
4998
3910
 
4999
3911
        return(len);
5000
3912
}
5001
 
#endif
5002
 
 
5003
3913
#else /* !UNIV_HOTBACKUP */
5004
3914
/********************************************************************//**
5005
3915
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */