~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
4
 
Copyright (c) 2008, Google Inc.
 
3
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
 
4
Copyright (C) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
7
7
Google, Inc. Those modifications are gratefully acknowledged and are described
52
52
#include "log0recv.h"
53
53
#include "page0zip.h"
54
54
 
 
55
#include <drizzled/errmsg_print.h>
 
56
 
55
57
/*
56
58
                IMPLEMENTATION OF THE BUFFER POOL
57
59
                =================================
84
86
The buffer buf_pool contains a single mutex which protects all the
85
87
control data structures of the buf_pool. The content of a buffer frame is
86
88
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.
 
89
These locks can be locked and unlocked without owning the buf_pool->mutex.
88
90
The OS events in the buf_pool struct can be waited for without owning the
89
 
buf_pool mutex.
 
91
buf_pool->mutex.
90
92
 
91
 
The buf_pool mutex is a hot-spot in main memory, causing a lot of
 
93
The buf_pool->mutex is a hot-spot in main memory, causing a lot of
92
94
memory bus traffic on multiprocessor systems when processors
93
95
alternately access the mutex. On our Pentium, the mutex is accessed
94
96
maybe every 10 microseconds. We gave up the solution to have mutexes
95
97
for each control block, for instance, because it seemed to be
96
98
complicated.
97
99
 
98
 
A solution to reduce mutex contention of the buf_pool mutex is to
 
100
A solution to reduce mutex contention of the buf_pool->mutex is to
99
101
create a separate mutex for the page hash table. On Pentium,
100
102
accessing the hash table takes 2 microseconds, about half
101
 
of the total buf_pool mutex hold time.
 
103
of the total buf_pool->mutex hold time.
102
104
 
103
105
                Control blocks
104
106
                --------------
153
155
which we can use when we want to artificially age a page in the
154
156
buf_pool. This is used if we know that some page is not needed
155
157
again for some time: we insert the block right after the pointer,
156
 
causing it to be replaced sooner than would noramlly be the case.
 
158
causing it to be replaced sooner than would normally be the case.
157
159
Currently this aging mechanism is used for read-ahead mechanism
158
160
of pages, and it can also be used when there is a scan of a full
159
161
table which cannot fit in the memory. Putting the pages near the
160
 
of the LRU list, we make sure that most of the buf_pool stays in the
161
 
main memory, undisturbed.
 
162
end of the LRU list, we make sure that most of the buf_pool stays
 
163
in the main memory, undisturbed.
162
164
 
163
165
The unzip_LRU list contains a subset of the common LRU list.  The
164
166
blocks on the unzip_LRU list hold a compressed file page and the
172
174
holding file pages that have been modified in the memory
173
175
but not written to disk yet. The block with the oldest modification
174
176
which has not yet been written to disk is at the end of the chain.
 
177
The access to this list is protected by buf_pool->flush_list_mutex.
175
178
 
176
179
The chain of unmodified compressed blocks (buf_pool->zip_clean)
177
180
contains the control blocks (buf_page_t) of those compressed pages
242
245
#ifndef UNIV_HOTBACKUP
243
246
/** Value in microseconds */
244
247
static const int WAIT_FOR_READ  = 5000;
245
 
 
246
 
/** The buffer buf_pool of the database */
247
 
UNIV_INTERN buf_pool_t* buf_pool = NULL;
248
 
 
249
 
/** mutex protecting the buffer pool struct and control blocks, except the
250
 
read-write lock in them */
251
 
UNIV_INTERN mutex_t             buf_pool_mutex;
252
 
/** mutex protecting the control blocks of compressed-only pages
253
 
(of type buf_page_t, not buf_block_t) */
254
 
UNIV_INTERN mutex_t             buf_pool_zip_mutex;
 
248
/** Number of attemtps made to read in a page in the buffer pool */
 
249
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
 
250
 
 
251
/** The buffer pools of the database */
 
252
UNIV_INTERN buf_pool_t* buf_pool_ptr;
255
253
 
256
254
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
257
255
static ulint    buf_dbg_counter = 0; /*!< This is used to insert validation
258
 
                                        operations in excution in the
 
256
                                        operations in execution in the
259
257
                                        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;
263
258
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
264
259
#ifdef UNIV_DEBUG
265
260
/** If this is set TRUE, the program prints info whenever
267
262
UNIV_INTERN ibool               buf_debug_prints = FALSE;
268
263
#endif /* UNIV_DEBUG */
269
264
 
 
265
#ifdef UNIV_PFS_RWLOCK
 
266
/* Keys to register buffer block related rwlocks and mutexes with
 
267
performance schema */
 
268
UNIV_INTERN mysql_pfs_key_t     buf_block_lock_key;
 
269
# ifdef UNIV_SYNC_DEBUG
 
270
UNIV_INTERN mysql_pfs_key_t     buf_block_debug_latch_key;
 
271
# endif /* UNIV_SYNC_DEBUG */
 
272
#endif /* UNIV_PFS_RWLOCK */
 
273
 
 
274
#ifdef UNIV_PFS_MUTEX
 
275
UNIV_INTERN mysql_pfs_key_t     buffer_block_mutex_key;
 
276
UNIV_INTERN mysql_pfs_key_t     buf_pool_mutex_key;
 
277
UNIV_INTERN mysql_pfs_key_t     buf_pool_zip_mutex_key;
 
278
UNIV_INTERN mysql_pfs_key_t     flush_list_mutex_key;
 
279
#endif /* UNIV_PFS_MUTEX */
 
280
 
 
281
#if defined UNIV_PFS_MUTEX || defined UNIV_PFS_RWLOCK
 
282
# ifndef PFS_SKIP_BUFFER_MUTEX_RWLOCK
 
283
 
 
284
/* Buffer block mutexes and rwlocks can be registered
 
285
in one group rather than individually. If PFS_GROUP_BUFFER_SYNC
 
286
is defined, register buffer block mutex and rwlock
 
287
in one group after their initialization. */
 
288
#  define PFS_GROUP_BUFFER_SYNC
 
289
 
 
290
/* This define caps the number of mutexes/rwlocks can
 
291
be registered with performance schema. Developers can
 
292
modify this define if necessary. Please note, this would
 
293
be effective only if PFS_GROUP_BUFFER_SYNC is defined. */
 
294
#  define PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER    ULINT_MAX
 
295
 
 
296
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
 
297
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
 
298
 
270
299
/** A chunk of buffers.  The buffer pool is allocated in chunks. */
271
300
struct buf_chunk_struct{
272
301
        ulint           mem_size;       /*!< allocated size of the chunk */
278
307
#endif /* !UNIV_HOTBACKUP */
279
308
 
280
309
/********************************************************************//**
 
310
Gets the smallest oldest_modification lsn for any page in the pool. Returns
 
311
zero if all modified pages have been flushed to disk.
 
312
@return oldest modification in pool, zero if none */
 
313
UNIV_INTERN
 
314
ib_uint64_t
 
315
buf_pool_get_oldest_modification(void)
 
316
/*==================================*/
 
317
{
 
318
        ulint           i;
 
319
        buf_page_t*     bpage;
 
320
        ib_uint64_t     lsn = 0;
 
321
        ib_uint64_t     oldest_lsn = 0;
 
322
 
 
323
        /* When we traverse all the flush lists we don't want another
 
324
        thread to add a dirty page to any flush list. */
 
325
        log_flush_order_mutex_enter();
 
326
 
 
327
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
328
                buf_pool_t*     buf_pool;
 
329
 
 
330
                buf_pool = buf_pool_from_array(i);
 
331
 
 
332
                buf_flush_list_mutex_enter(buf_pool);
 
333
 
 
334
                bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
 
335
 
 
336
                if (bpage != NULL) {
 
337
                        ut_ad(bpage->in_flush_list);
 
338
                        lsn = bpage->oldest_modification;
 
339
                }
 
340
 
 
341
                buf_flush_list_mutex_exit(buf_pool);
 
342
 
 
343
                if (!oldest_lsn || oldest_lsn > lsn) {
 
344
                        oldest_lsn = lsn;
 
345
                }
 
346
        }
 
347
 
 
348
        log_flush_order_mutex_exit();
 
349
 
 
350
        /* The returned answer may be out of date: the flush_list can
 
351
        change after the mutex has been released. */
 
352
 
 
353
        return(oldest_lsn);
 
354
}
 
355
 
 
356
/********************************************************************//**
 
357
Get total buffer pool statistics. */
 
358
UNIV_INTERN
 
359
void
 
360
buf_get_total_list_len(
 
361
/*===================*/
 
362
        ulint*          LRU_len,        /*!< out: length of all LRU lists */
 
363
        ulint*          free_len,       /*!< out: length of all free lists */
 
364
        ulint*          flush_list_len) /*!< out: length of all flush lists */
 
365
{
 
366
        ulint           i;
 
367
 
 
368
        *LRU_len = 0;
 
369
        *free_len = 0;
 
370
        *flush_list_len = 0;
 
371
 
 
372
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
373
                buf_pool_t*     buf_pool;
 
374
 
 
375
                buf_pool = buf_pool_from_array(i);
 
376
                *LRU_len += UT_LIST_GET_LEN(buf_pool->LRU);
 
377
                *free_len += UT_LIST_GET_LEN(buf_pool->free);
 
378
                *flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
 
379
        }
 
380
}
 
381
 
 
382
/********************************************************************//**
 
383
Get total buffer pool statistics. */
 
384
UNIV_INTERN
 
385
void
 
386
buf_get_total_stat(
 
387
/*===============*/
 
388
        buf_pool_stat_t*        tot_stat)       /*!< out: buffer pool stats */
 
389
{
 
390
        ulint                   i;
 
391
 
 
392
        memset(tot_stat, 0, sizeof(*tot_stat));
 
393
 
 
394
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
395
                buf_pool_stat_t*buf_stat;
 
396
                buf_pool_t*     buf_pool;
 
397
 
 
398
                buf_pool = buf_pool_from_array(i);
 
399
 
 
400
                buf_stat = &buf_pool->stat;
 
401
                tot_stat->n_page_gets += buf_stat->n_page_gets;
 
402
                tot_stat->n_pages_read += buf_stat->n_pages_read;
 
403
                tot_stat->n_pages_written += buf_stat->n_pages_written;
 
404
                tot_stat->n_pages_created += buf_stat->n_pages_created;
 
405
                tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read;
 
406
                tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted;
 
407
                tot_stat->n_pages_made_young += buf_stat->n_pages_made_young;
 
408
 
 
409
                tot_stat->n_pages_not_made_young +=
 
410
                        buf_stat->n_pages_not_made_young;
 
411
        }
 
412
}
 
413
 
 
414
/********************************************************************//**
 
415
Allocates a buffer block.
 
416
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
 
417
UNIV_INTERN
 
418
buf_block_t*
 
419
buf_block_alloc(
 
420
/*============*/
 
421
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
422
        ulint           zip_size)       /*!< in: compressed page size in bytes,
 
423
                                        or 0 if uncompressed tablespace */
 
424
{
 
425
        buf_block_t*    block;
 
426
        ulint           index;
 
427
        static ulint    buf_pool_index;
 
428
 
 
429
        if (buf_pool == NULL) {
 
430
                /* We are allocating memory from any buffer pool, ensure
 
431
                we spread the grace on all buffer pool instances. */
 
432
                index = buf_pool_index++ % srv_buf_pool_instances;
 
433
                buf_pool = buf_pool_from_array(index);
 
434
        }
 
435
 
 
436
        block = buf_LRU_get_free_block(buf_pool, zip_size);
 
437
 
 
438
        buf_block_set_state(block, BUF_BLOCK_MEMORY);
 
439
 
 
440
        return(block);
 
441
}
 
442
 
 
443
/********************************************************************//**
281
444
Calculates a page checksum which is stored to the page when it is written
282
445
to a file. Note that we must be careful to calculate the same value on
283
446
32-bit and 64-bit architectures.
361
524
                ib_uint64_t     current_lsn;
362
525
 
363
526
                if (log_peek_lsn(&current_lsn)
364
 
                    && current_lsn < mach_read_ull(read_buf + FIL_PAGE_LSN)) {
 
527
                    && UNIV_UNLIKELY
 
528
                    (current_lsn
 
529
                     < mach_read_from_8(read_buf + FIL_PAGE_LSN))) {
365
530
                        ut_print_timestamp(stderr);
366
531
 
367
 
                        fprintf(stderr,
368
 
                                "  InnoDB: Error: page %lu log sequence number"
369
 
                                " %"PRIu64"\n"
370
 
                                "InnoDB: is in the future! Current system "
371
 
                                "log sequence number %"PRIu64".\n"
372
 
                                "InnoDB: Your database may be corrupt or "
373
 
                                "you may have copied the InnoDB\n"
374
 
                                "InnoDB: tablespace but not the InnoDB "
375
 
                                "log files. See\n"
376
 
                                "InnoDB: " REFMAN "forcing-recovery.html\n"
377
 
                                "InnoDB: for more information.\n",
378
 
                                (ulong) mach_read_from_4(read_buf
379
 
                                                         + FIL_PAGE_OFFSET),
380
 
                                mach_read_ull(read_buf + FIL_PAGE_LSN),
381
 
                                current_lsn);
 
532
                        drizzled::errmsg_printf(drizzled::error::INFO,
 
533
                                                "InnoDB: Error: page %lu log sequence number %"PRIu64". "
 
534
                                                "InnoDB: is in the future! Current system log sequence number %"PRIu64". "
 
535
                                                "Your database may be corrupt or you may have copied the InnoDB tablespace but not the InnoDB log files. See "
 
536
                                                " " REFMAN "forcing-recovery.html for more information. ",
 
537
                                                (ulong) mach_read_from_4(read_buf
 
538
                                                                         + FIL_PAGE_OFFSET),
 
539
                                                mach_read_from_8(read_buf + FIL_PAGE_LSN),
 
540
                                                current_lsn);
382
541
                }
383
542
        }
384
543
#endif
574
733
#endif /* !UNIV_HOTBACKUP */
575
734
 
576
735
        switch (fil_page_get_type(read_buf)) {
 
736
                index_id_t      index_id;
577
737
        case FIL_PAGE_INDEX:
 
738
                index_id = btr_page_get_index_id(read_buf);
578
739
                fprintf(stderr,
579
740
                        "InnoDB: Page may be an index page where"
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)));
 
741
                        " index id is %llu\n",
 
742
                        (ullint) index_id);
585
743
#ifndef UNIV_HOTBACKUP
586
 
                index = dict_index_find_on_id_low(
587
 
                        btr_page_get_index_id(read_buf));
 
744
                index = dict_index_find_on_id_low(index_id);
588
745
                if (index) {
589
746
                        fputs("InnoDB: (", stderr);
590
747
                        dict_index_name_print(stderr, NULL, index);
636
793
}
637
794
 
638
795
#ifndef UNIV_HOTBACKUP
 
796
 
 
797
# ifdef PFS_GROUP_BUFFER_SYNC
 
798
/********************************************************************//**
 
799
This function registers mutexes and rwlocks in buffer blocks with
 
800
performance schema. If PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER is
 
801
defined to be a value less than chunk->size, then only mutexes
 
802
and rwlocks in the first PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER
 
803
blocks are registered. */
 
804
static
 
805
void
 
806
pfs_register_buffer_block(
 
807
/*======================*/
 
808
        buf_chunk_t*    chunk)          /*!< in/out: chunk of buffers */
 
809
{
 
810
        ulint           i;
 
811
        ulint           num_to_register;
 
812
        buf_block_t*    block;
 
813
 
 
814
        block = chunk->blocks;
 
815
 
 
816
        num_to_register = ut_min(chunk->size,
 
817
                                 PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER);
 
818
 
 
819
        for (i = 0; i < num_to_register; i++) {
 
820
                mutex_t*        mutex;
 
821
                rw_lock_t*      rwlock;
 
822
 
 
823
#  ifdef UNIV_PFS_MUTEX
 
824
                mutex = &block->mutex;
 
825
                ut_a(!mutex->pfs_psi);
 
826
                mutex->pfs_psi = (PSI_server)
 
827
                        ? PSI_server->init_mutex(buffer_block_mutex_key, mutex)
 
828
                        : NULL;
 
829
#  endif /* UNIV_PFS_MUTEX */
 
830
 
 
831
#  ifdef UNIV_PFS_RWLOCK
 
832
                rwlock = &block->lock;
 
833
                ut_a(!rwlock->pfs_psi);
 
834
                rwlock->pfs_psi = (PSI_server)
 
835
                        ? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
 
836
                        : NULL;
 
837
#  endif /* UNIV_PFS_RWLOCK */
 
838
                block++;
 
839
        }
 
840
}
 
841
# endif /* PFS_GROUP_BUFFER_SYNC */
 
842
 
639
843
/********************************************************************//**
640
844
Initializes a buffer control block when the buf_pool is created. */
641
845
static
642
846
void
643
847
buf_block_init(
644
848
/*===========*/
645
 
        buf_block_t*    block,  /*!< in: pointer to control block */
646
 
        byte*           frame)  /*!< in: pointer to buffer frame */
 
849
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
850
        buf_block_t*    block,          /*!< in: pointer to control block */
 
851
        byte*           frame)          /*!< in: pointer to buffer frame */
647
852
{
648
853
        UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
649
854
 
650
855
        block->frame = frame;
651
856
 
 
857
        block->page.buf_pool_index = buf_pool_index(buf_pool);
652
858
        block->page.state = BUF_BLOCK_NOT_USED;
653
859
        block->page.buf_fix_count = 0;
654
860
        block->page.io_fix = BUF_IO_NONE;
662
868
        block->check_index_page_at_flush = FALSE;
663
869
        block->index = NULL;
664
870
 
 
871
        block->is_hashed = FALSE;
 
872
 
665
873
#ifdef UNIV_DEBUG
666
874
        block->page.in_page_hash = FALSE;
667
875
        block->page.in_zip_hash = FALSE;
675
883
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
676
884
        page_zip_des_init(&block->page.zip);
677
885
 
678
 
        mutex_create(&block->mutex, SYNC_BUF_BLOCK);
679
 
 
680
 
        rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
 
886
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
 
887
        /* If PFS_SKIP_BUFFER_MUTEX_RWLOCK is defined, skip registration
 
888
        of buffer block mutex/rwlock with performance schema. If
 
889
        PFS_GROUP_BUFFER_SYNC is defined, skip the registration
 
890
        since buffer block mutex/rwlock will be registered later in
 
891
        pfs_register_buffer_block() */
 
892
 
 
893
        mutex_create(PFS_NOT_INSTRUMENTED, &block->mutex, SYNC_BUF_BLOCK);
 
894
        rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
 
895
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
 
896
        mutex_create(buffer_block_mutex_key, &block->mutex, SYNC_BUF_BLOCK);
 
897
        rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
 
898
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
 
899
 
681
900
        ut_ad(rw_lock_validate(&(block->lock)));
682
901
 
683
902
#ifdef UNIV_SYNC_DEBUG
684
 
        rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
 
903
        rw_lock_create(buf_block_debug_latch_key,
 
904
                       &block->debug_latch, SYNC_NO_ORDER_CHECK);
685
905
#endif /* UNIV_SYNC_DEBUG */
686
906
}
687
907
 
692
912
buf_chunk_t*
693
913
buf_chunk_init(
694
914
/*===========*/
 
915
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
695
916
        buf_chunk_t*    chunk,          /*!< out: chunk of buffers */
696
917
        ulint           mem_size)       /*!< in: requested size in bytes */
697
918
{
716
937
 
717
938
        /* Allocate the block descriptors from
718
939
        the start of the memory block. */
719
 
        chunk->blocks = chunk->mem;
 
940
        chunk->blocks = static_cast<buf_block_struct *>(chunk->mem);
720
941
 
721
942
        /* Align a pointer to the first frame.  Note that when
722
943
        os_large_page_size is smaller than UNIV_PAGE_SIZE,
723
944
        we may allocate one fewer block than requested.  When
724
945
        it is bigger, we may allocate more blocks than requested. */
725
946
 
726
 
        frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
 
947
        frame = static_cast<unsigned char *>(ut_align(chunk->mem, UNIV_PAGE_SIZE));
727
948
        chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
728
949
                - (frame != chunk->mem);
729
950
 
747
968
 
748
969
        for (i = chunk->size; i--; ) {
749
970
 
750
 
                buf_block_init(block, frame);
 
971
                buf_block_init(buf_pool, block, frame);
751
972
 
752
973
#ifdef HAVE_VALGRIND
753
974
                /* Wipe contents of frame to eliminate a Purify warning */
755
976
#endif
756
977
                /* Add the block to the free list */
757
978
                UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
 
979
 
758
980
                ut_d(block->page.in_free_list = TRUE);
 
981
                ut_ad(buf_pool_from_block(block) == buf_pool);
759
982
 
760
983
                block++;
761
984
                frame += UNIV_PAGE_SIZE;
762
985
        }
763
986
 
 
987
#ifdef PFS_GROUP_BUFFER_SYNC
 
988
        pfs_register_buffer_block(chunk);
 
989
#endif
764
990
        return(chunk);
765
991
}
766
992
 
779
1005
        buf_block_t*    block;
780
1006
        ulint           i;
781
1007
 
782
 
        ut_ad(buf_pool);
783
 
        ut_ad(buf_pool_mutex_own());
784
 
 
785
1008
        block = chunk->blocks;
786
1009
 
787
1010
        for (i = chunk->size; i--; block++) {
802
1025
buf_block_t*
803
1026
buf_pool_contains_zip(
804
1027
/*==================*/
805
 
        const void*     data)   /*!< in: pointer to compressed page */
 
1028
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1029
        const void*     data)           /*!< in: pointer to compressed page */
806
1030
{
807
1031
        ulint           n;
808
1032
        buf_chunk_t*    chunk = buf_pool->chunks;
809
1033
 
 
1034
        ut_ad(buf_pool);
 
1035
        ut_ad(buf_pool_mutex_own(buf_pool));
810
1036
        for (n = buf_pool->n_chunks; n--; chunk++) {
 
1037
 
811
1038
                buf_block_t* block = buf_chunk_contains_zip(chunk, data);
812
1039
 
813
1040
                if (block) {
831
1058
        buf_block_t*    block;
832
1059
        ulint           i;
833
1060
 
834
 
        ut_ad(buf_pool);
835
 
        ut_ad(buf_pool_mutex_own());
836
 
 
837
1061
        block = chunk->blocks;
838
1062
 
839
1063
        for (i = chunk->size; i--; block++) {
883
1107
        const buf_block_t*      block;
884
1108
        ulint                   i;
885
1109
 
886
 
        ut_ad(buf_pool);
887
 
        ut_ad(buf_pool_mutex_own());
888
 
 
889
1110
        block = chunk->blocks;
890
1111
 
891
1112
        for (i = chunk->size; i--; block++) {
905
1126
void
906
1127
buf_chunk_free(
907
1128
/*===========*/
 
1129
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
908
1130
        buf_chunk_t*    chunk)          /*!< out: chunk of buffers */
909
1131
{
910
1132
        buf_block_t*            block;
911
1133
        const buf_block_t*      block_end;
912
1134
 
913
 
        ut_ad(buf_pool_mutex_own());
 
1135
        ut_ad(buf_pool_mutex_own(buf_pool));
914
1136
 
915
1137
        block_end = chunk->blocks + chunk->size;
916
1138
 
938
1160
}
939
1161
 
940
1162
/********************************************************************//**
941
 
Creates the buffer pool.
942
 
@return own: buf_pool object, NULL if not enough memory or error */
943
 
UNIV_INTERN
944
 
buf_pool_t*
945
 
buf_pool_init(void)
946
 
/*===============*/
947
 
{
 
1163
Set buffer pool size variables after resizing it */
 
1164
static
 
1165
void
 
1166
buf_pool_set_sizes(void)
 
1167
/*====================*/
 
1168
{
 
1169
        ulint   i;
 
1170
        ulint   curr_size = 0;
 
1171
 
 
1172
        buf_pool_mutex_enter_all();
 
1173
 
 
1174
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1175
                buf_pool_t*     buf_pool;
 
1176
 
 
1177
                buf_pool = buf_pool_from_array(i);
 
1178
                curr_size += buf_pool->curr_pool_size;
 
1179
        }
 
1180
 
 
1181
        srv_buf_pool_curr_size = curr_size;
 
1182
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1183
 
 
1184
        buf_pool_mutex_exit_all();
 
1185
}
 
1186
 
 
1187
/********************************************************************//**
 
1188
Initialize a buffer pool instance.
 
1189
@return DB_SUCCESS if all goes well. */
 
1190
static
 
1191
ulint
 
1192
buf_pool_init_instance(
 
1193
/*===================*/
 
1194
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1195
        ulint           buf_pool_size,  /*!< in: size in bytes */
 
1196
        ulint           instance_no)    /*!< in: id of the instance */
 
1197
{
 
1198
        ulint           i;
948
1199
        buf_chunk_t*    chunk;
949
 
        ulint           i;
950
 
 
951
 
        buf_pool = mem_zalloc(sizeof(buf_pool_t));
952
1200
 
953
1201
        /* 1. Initialize general fields
954
1202
        ------------------------------- */
955
 
        mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
956
 
        mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
957
 
 
958
 
        buf_pool_mutex_enter();
959
 
 
960
 
        buf_pool->n_chunks = 1;
961
 
        buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
962
 
 
963
 
        UT_LIST_INIT(buf_pool->free);
964
 
 
965
 
        if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
966
 
                mem_free(chunk);
967
 
                mem_free(buf_pool);
968
 
                buf_pool = NULL;
969
 
                return(NULL);
 
1203
        mutex_create(buf_pool_mutex_key,
 
1204
                     &buf_pool->mutex, SYNC_BUF_POOL);
 
1205
        mutex_create(buf_pool_zip_mutex_key,
 
1206
                     &buf_pool->zip_mutex, SYNC_BUF_BLOCK);
 
1207
 
 
1208
        buf_pool_mutex_enter(buf_pool);
 
1209
 
 
1210
        if (buf_pool_size > 0) {
 
1211
                buf_pool->n_chunks = 1;
 
1212
                void *chunk_ptr= mem_zalloc((sizeof *chunk));
 
1213
                buf_pool->chunks = chunk = static_cast<buf_chunk_t *>(chunk_ptr);
 
1214
 
 
1215
                UT_LIST_INIT(buf_pool->free);
 
1216
 
 
1217
                if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
 
1218
                        mem_free(chunk);
 
1219
                        mem_free(buf_pool);
 
1220
 
 
1221
                        buf_pool_mutex_exit(buf_pool);
 
1222
 
 
1223
                        return(DB_ERROR);
 
1224
                }
 
1225
 
 
1226
                buf_pool->instance_no = instance_no;
 
1227
                buf_pool->old_pool_size = buf_pool_size;
 
1228
                buf_pool->curr_size = chunk->size;
 
1229
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1230
 
 
1231
                buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
 
1232
                buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
 
1233
                
 
1234
                buf_pool->last_printout_time = ut_time();
970
1235
        }
971
 
 
972
 
        srv_buf_pool_old_size = srv_buf_pool_size;
973
 
        buf_pool->curr_size = chunk->size;
974
 
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
975
 
 
976
 
        buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
977
 
        buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
978
 
 
979
 
        buf_pool->last_printout_time = time(NULL);
980
 
 
981
1236
        /* 2. Initialize flushing fields
982
1237
        -------------------------------- */
983
1238
 
 
1239
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
 
1240
                     SYNC_BUF_FLUSH_LIST);
 
1241
 
984
1242
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
985
1243
                buf_pool->no_flush[i] = os_event_create(NULL);
986
1244
        }
987
1245
 
988
1246
        /* 3. Initialize LRU fields
989
1247
        --------------------------- */
990
 
        /* All fields are initialized by mem_zalloc(). */
991
 
 
992
 
        buf_pool_mutex_exit();
993
 
 
994
 
        btr_search_sys_create(buf_pool->curr_size
995
 
                              * UNIV_PAGE_SIZE / sizeof(void*) / 64);
996
 
 
997
 
        /* 4. Initialize the buddy allocator fields */
998
 
        /* All fields are initialized by mem_zalloc(). */
999
 
 
1000
 
        return(buf_pool);
 
1248
 
 
1249
        /* All fields are initialized by mem_zalloc(). */
 
1250
 
 
1251
        buf_pool_mutex_exit(buf_pool);
 
1252
 
 
1253
        return(DB_SUCCESS);
1001
1254
}
1002
1255
 
1003
1256
/********************************************************************//**
1004
 
Frees the buffer pool at shutdown.  This must not be invoked before
1005
 
freeing all mutexes. */
1006
 
UNIV_INTERN
 
1257
free one buffer pool instance */
 
1258
static
1007
1259
void
1008
 
buf_pool_free(void)
1009
 
/*===============*/
 
1260
buf_pool_free_instance(
 
1261
/*===================*/
 
1262
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
 
1263
                                        to free */
1010
1264
{
1011
1265
        buf_chunk_t*    chunk;
1012
1266
        buf_chunk_t*    chunks;
1023
1277
        mem_free(buf_pool->chunks);
1024
1278
        hash_table_free(buf_pool->page_hash);
1025
1279
        hash_table_free(buf_pool->zip_hash);
1026
 
        mem_free(buf_pool);
1027
 
        buf_pool = NULL;
1028
 
}
1029
 
 
 
1280
}
 
1281
 
 
1282
/********************************************************************//**
 
1283
Creates the buffer pool.
 
1284
@return DB_SUCCESS if success, DB_ERROR if not enough memory or error */
 
1285
UNIV_INTERN
 
1286
ulint
 
1287
buf_pool_init(
 
1288
/*==========*/
 
1289
        ulint   total_size,     /*!< in: size of the total pool in bytes */
 
1290
        ulint   n_instances)    /*!< in: number of instances */
 
1291
{
 
1292
        ulint           i;
 
1293
        const ulint     size    = total_size / n_instances;
 
1294
 
 
1295
        ut_ad(n_instances > 0);
 
1296
        ut_ad(n_instances <= MAX_BUFFER_POOLS);
 
1297
        ut_ad(n_instances == srv_buf_pool_instances);
 
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
        void *buf_pool_void_ptr= mem_zalloc(n_instances * sizeof *buf_pool_ptr);
 
1303
        buf_pool_ptr = static_cast<buf_pool_struct *>(buf_pool_void_ptr);
 
1304
 
 
1305
        for (i = 0; i < n_instances; i++) {
 
1306
                buf_pool_t*     ptr     = &buf_pool_ptr[i];
 
1307
 
 
1308
                if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
 
1309
 
 
1310
                        /* Free all the instances created so far. */
 
1311
                        buf_pool_free(i);
 
1312
 
 
1313
                        return(DB_ERROR);
 
1314
                }
 
1315
        }
 
1316
 
 
1317
        buf_pool_set_sizes();
 
1318
        buf_LRU_old_ratio_update(100 * 3/ 8, FALSE);
 
1319
 
 
1320
        btr_search_sys_create(buf_pool_get_curr_size() / sizeof(void*) / 64);
 
1321
 
 
1322
        return(DB_SUCCESS);
 
1323
}
 
1324
 
 
1325
/********************************************************************//**
 
1326
Frees the buffer pool at shutdown.  This must not be invoked before
 
1327
freeing all mutexes. */
 
1328
UNIV_INTERN
 
1329
void
 
1330
buf_pool_free(
 
1331
/*==========*/
 
1332
        ulint   n_instances)    /*!< in: numbere of instances to free */
 
1333
{
 
1334
        ulint   i;
 
1335
 
 
1336
        for (i = 0; i < n_instances; i++) {
 
1337
                buf_pool_free_instance(buf_pool_from_array(i));
 
1338
        }
 
1339
 
 
1340
        mem_free(buf_pool_ptr);
 
1341
        buf_pool_ptr = NULL;
 
1342
}
 
1343
 
 
1344
/********************************************************************//**
 
1345
Drops adaptive hash index for a buffer pool instance. */
 
1346
static
 
1347
void
 
1348
buf_pool_drop_hash_index_instance(
 
1349
/*==============================*/
 
1350
        buf_pool_t*     buf_pool,               /*!< in: buffer pool instance */
 
1351
        ibool*          released_search_latch)  /*!< out: flag for signalling
 
1352
                                                whether the search latch was
 
1353
                                                released */
 
1354
{
 
1355
        buf_chunk_t*    chunks  = buf_pool->chunks;
 
1356
        buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
 
1357
 
 
1358
        while (--chunk >= chunks) {
 
1359
                ulint           i;
 
1360
                buf_block_t*    block   = chunk->blocks;
 
1361
 
 
1362
                for (i = chunk->size; i--; block++) {
 
1363
                        /* block->is_hashed cannot be modified
 
1364
                        when we have an x-latch on btr_search_latch;
 
1365
                        see the comment in buf0buf.h */
 
1366
                        
 
1367
                        if (!block->is_hashed) {
 
1368
                                continue;
 
1369
                        }
 
1370
                        
 
1371
                        /* To follow the latching order, we
 
1372
                        have to release btr_search_latch
 
1373
                        before acquiring block->latch. */
 
1374
                        rw_lock_x_unlock(&btr_search_latch);
 
1375
                        /* When we release the search latch,
 
1376
                        we must rescan all blocks, because
 
1377
                        some may become hashed again. */
 
1378
                        *released_search_latch = TRUE;
 
1379
                        
 
1380
                        rw_lock_x_lock(&block->lock);
 
1381
                        
 
1382
                        /* This should be guaranteed by the
 
1383
                        callers, which will be holding
 
1384
                        btr_search_enabled_mutex. */
 
1385
                        ut_ad(!btr_search_enabled);
 
1386
                        
 
1387
                        /* Because we did not buffer-fix the
 
1388
                        block by calling buf_block_get_gen(),
 
1389
                        it is possible that the block has been
 
1390
                        allocated for some other use after
 
1391
                        btr_search_latch was released above.
 
1392
                        We do not care which file page the
 
1393
                        block is mapped to.  All we want to do
 
1394
                        is to drop any hash entries referring
 
1395
                        to the page. */
 
1396
                        
 
1397
                        /* It is possible that
 
1398
                        block->page.state != BUF_FILE_PAGE.
 
1399
                        Even that does not matter, because
 
1400
                        btr_search_drop_page_hash_index() will
 
1401
                        check block->is_hashed before doing
 
1402
                        anything.  block->is_hashed can only
 
1403
                        be set on uncompressed file pages. */
 
1404
                        
 
1405
                        btr_search_drop_page_hash_index(block);
 
1406
                        
 
1407
                        rw_lock_x_unlock(&block->lock);
 
1408
                        
 
1409
                        rw_lock_x_lock(&btr_search_latch);
 
1410
                        
 
1411
                        ut_ad(!btr_search_enabled);
 
1412
                }
 
1413
        }
 
1414
}
 
1415
 
1030
1416
/********************************************************************//**
1031
1417
Drops the adaptive hash index.  To prevent a livelock, this function
1032
1418
is only to be called while holding btr_search_latch and while
1044
1430
        ut_ad(!btr_search_enabled);
1045
1431
 
1046
1432
        do {
1047
 
                buf_chunk_t*    chunks  = buf_pool->chunks;
1048
 
                buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
 
1433
                ulint   i;
1049
1434
 
1050
1435
                released_search_latch = FALSE;
1051
1436
 
1052
 
                while (--chunk >= chunks) {
1053
 
                        buf_block_t*    block   = chunk->blocks;
1054
 
                        ulint           i       = chunk->size;
1055
 
 
1056
 
                        for (; i--; block++) {
1057
 
                                /* block->is_hashed cannot be modified
1058
 
                                when we have an x-latch on btr_search_latch;
1059
 
                                see the comment in buf0buf.h */
1060
 
 
1061
 
                                if (!block->is_hashed) {
1062
 
                                        continue;
1063
 
                                }
1064
 
 
1065
 
                                /* To follow the latching order, we
1066
 
                                have to release btr_search_latch
1067
 
                                before acquiring block->latch. */
1068
 
                                rw_lock_x_unlock(&btr_search_latch);
1069
 
                                /* When we release the search latch,
1070
 
                                we must rescan all blocks, because
1071
 
                                some may become hashed again. */
1072
 
                                released_search_latch = TRUE;
1073
 
 
1074
 
                                rw_lock_x_lock(&block->lock);
1075
 
 
1076
 
                                /* This should be guaranteed by the
1077
 
                                callers, which will be holding
1078
 
                                btr_search_enabled_mutex. */
1079
 
                                ut_ad(!btr_search_enabled);
1080
 
 
1081
 
                                /* Because we did not buffer-fix the
1082
 
                                block by calling buf_block_get_gen(),
1083
 
                                it is possible that the block has been
1084
 
                                allocated for some other use after
1085
 
                                btr_search_latch was released above.
1086
 
                                We do not care which file page the
1087
 
                                block is mapped to.  All we want to do
1088
 
                                is to drop any hash entries referring
1089
 
                                to the page. */
1090
 
 
1091
 
                                /* It is possible that
1092
 
                                block->page.state != BUF_FILE_PAGE.
1093
 
                                Even that does not matter, because
1094
 
                                btr_search_drop_page_hash_index() will
1095
 
                                check block->is_hashed before doing
1096
 
                                anything.  block->is_hashed can only
1097
 
                                be set on uncompressed file pages. */
1098
 
 
1099
 
                                btr_search_drop_page_hash_index(block);
1100
 
 
1101
 
                                rw_lock_x_unlock(&block->lock);
1102
 
 
1103
 
                                rw_lock_x_lock(&btr_search_latch);
1104
 
 
1105
 
                                ut_ad(!btr_search_enabled);
1106
 
                        }
 
1437
                for (i = 0; i < srv_buf_pool_instances; i++) {
 
1438
                        buf_pool_t*     buf_pool;
 
1439
 
 
1440
                        buf_pool = buf_pool_from_array(i);
 
1441
 
 
1442
                        buf_pool_drop_hash_index_instance(
 
1443
                                buf_pool, &released_search_latch);
1107
1444
                }
 
1445
 
1108
1446
        } while (released_search_latch);
1109
1447
}
1110
1448
 
1123
1461
{
1124
1462
        buf_page_t*     b;
1125
1463
        ulint           fold;
 
1464
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1126
1465
 
1127
 
        ut_ad(buf_pool_mutex_own());
 
1466
        ut_ad(buf_pool_mutex_own(buf_pool));
1128
1467
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1129
1468
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1130
1469
        ut_a(bpage->buf_fix_count == 0);
1131
1470
        ut_ad(bpage->in_LRU_list);
1132
1471
        ut_ad(!bpage->in_zip_hash);
1133
1472
        ut_ad(bpage->in_page_hash);
1134
 
        ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
 
1473
        ut_ad(bpage == buf_page_hash_get(buf_pool,
 
1474
                                         bpage->space, bpage->offset));
 
1475
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1135
1476
#ifdef UNIV_DEBUG
1136
1477
        switch (buf_page_get_state(bpage)) {
1137
1478
        case BUF_BLOCK_ZIP_FREE:
1187
1528
 
1188
1529
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
1189
1530
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
1190
 
 
1191
 
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
1192
1531
}
1193
1532
 
1194
1533
/********************************************************************//**
1195
 
Shrinks the buffer pool. */
 
1534
Shrinks a buffer pool instance. */
1196
1535
static
1197
1536
void
1198
 
buf_pool_shrink(
1199
 
/*============*/
1200
 
        ulint   chunk_size)     /*!< in: number of pages to remove */
 
1537
buf_pool_shrink_instance(
 
1538
/*=====================*/
 
1539
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
1540
        ulint           chunk_size)     /*!< in: number of pages to remove */
1201
1541
{
1202
1542
        buf_chunk_t*    chunks;
1203
1543
        buf_chunk_t*    chunk;
1206
1546
        buf_chunk_t*    max_chunk;
1207
1547
        buf_chunk_t*    max_free_chunk;
1208
1548
 
1209
 
        ut_ad(!buf_pool_mutex_own());
 
1549
        ut_ad(!buf_pool_mutex_own(buf_pool));
1210
1550
 
1211
1551
try_again:
1212
1552
        btr_search_disable(); /* Empty the adaptive hash index again */
1213
 
        buf_pool_mutex_enter();
 
1553
        buf_pool_mutex_enter(buf_pool);
1214
1554
 
1215
1555
shrink_again:
1216
1556
        if (buf_pool->n_chunks <= 1) {
1273
1613
 
1274
1614
                        mutex_enter(&block->mutex);
1275
1615
                        /* The following calls will temporarily
1276
 
                        release block->mutex and buf_pool_mutex.
 
1616
                        release block->mutex and buf_pool->mutex.
1277
1617
                        Therefore, we have to always retry,
1278
1618
                        even if !dirty && !nonfree. */
1279
1619
 
1289
1629
                        mutex_exit(&block->mutex);
1290
1630
                }
1291
1631
 
1292
 
                buf_pool_mutex_exit();
 
1632
                buf_pool_mutex_exit(buf_pool);
1293
1633
 
1294
1634
                /* Request for a flush of the chunk if it helps.
1295
1635
                Do not flush if there are non-free blocks, since
1298
1638
                        /* Avoid busy-waiting. */
1299
1639
                        os_thread_sleep(100000);
1300
1640
                } else if (dirty
1301
 
                           && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
1302
 
                           == ULINT_UNDEFINED) {
 
1641
                           && buf_flush_LRU(buf_pool, dirty)
 
1642
                              == ULINT_UNDEFINED) {
1303
1643
 
1304
 
                        buf_flush_wait_batch_end(BUF_FLUSH_LRU);
 
1644
                        buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
1305
1645
                }
1306
1646
 
1307
1647
                goto try_again;
1310
1650
        max_size = max_free_size;
1311
1651
        max_chunk = max_free_chunk;
1312
1652
 
1313
 
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1653
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
1314
1654
 
1315
1655
        /* Rewrite buf_pool->chunks.  Copy everything but max_chunk. */
1316
 
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
 
1656
        chunks = static_cast<buf_chunk_t *>(mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks));
1317
1657
        memcpy(chunks, buf_pool->chunks,
1318
1658
               (max_chunk - buf_pool->chunks) * sizeof *chunks);
1319
1659
        memcpy(chunks + (max_chunk - buf_pool->chunks),
1322
1662
               - (max_chunk + 1));
1323
1663
        ut_a(buf_pool->curr_size > max_chunk->size);
1324
1664
        buf_pool->curr_size -= max_chunk->size;
1325
 
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1665
        buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1326
1666
        chunk_size -= max_chunk->size;
1327
 
        buf_chunk_free(max_chunk);
 
1667
        buf_chunk_free(buf_pool, max_chunk);
1328
1668
        mem_free(buf_pool->chunks);
1329
1669
        buf_pool->chunks = chunks;
1330
1670
        buf_pool->n_chunks--;
1334
1674
 
1335
1675
                goto shrink_again;
1336
1676
        }
 
1677
        goto func_exit;
1337
1678
 
1338
1679
func_done:
1339
 
        srv_buf_pool_old_size = srv_buf_pool_size;
 
1680
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
1340
1681
func_exit:
1341
 
        buf_pool_mutex_exit();
 
1682
        buf_pool_mutex_exit(buf_pool);
1342
1683
        btr_search_enable();
1343
1684
}
1344
1685
 
1345
1686
/********************************************************************//**
1346
 
Rebuild buf_pool->page_hash. */
1347
 
static
1348
 
void
1349
 
buf_pool_page_hash_rebuild(void)
1350
 
/*============================*/
 
1687
Shrinks the buffer pool. */
 
1688
static
 
1689
void
 
1690
buf_pool_shrink(
 
1691
/*============*/
 
1692
        ulint   chunk_size)     /*!< in: number of pages to remove */
 
1693
{
 
1694
        ulint   i;
 
1695
 
 
1696
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1697
                buf_pool_t*     buf_pool;
 
1698
                ulint           instance_chunk_size;
 
1699
 
 
1700
                instance_chunk_size = chunk_size / srv_buf_pool_instances;
 
1701
                buf_pool = buf_pool_from_array(i);
 
1702
                buf_pool_shrink_instance(buf_pool, instance_chunk_size);
 
1703
        }
 
1704
 
 
1705
        buf_pool_set_sizes();
 
1706
}
 
1707
 
 
1708
/********************************************************************//**
 
1709
Rebuild buf_pool->page_hash for a buffer pool instance. */
 
1710
static
 
1711
void
 
1712
buf_pool_page_hash_rebuild_instance(
 
1713
/*================================*/
 
1714
        buf_pool_t*     buf_pool)               /*!< in: buffer pool instance */
1351
1715
{
1352
1716
        ulint           i;
 
1717
        buf_page_t*     b;
 
1718
        buf_chunk_t*    chunk;
1353
1719
        ulint           n_chunks;
1354
 
        buf_chunk_t*    chunk;
 
1720
        hash_table_t*   zip_hash;
1355
1721
        hash_table_t*   page_hash;
1356
 
        hash_table_t*   zip_hash;
1357
 
        buf_page_t*     b;
1358
1722
 
1359
 
        buf_pool_mutex_enter();
 
1723
        buf_pool_mutex_enter(buf_pool);
1360
1724
 
1361
1725
        /* Free, create, and populate the hash table. */
1362
1726
        hash_table_free(buf_pool->page_hash);
1409
1773
                            buf_page_address_fold(b->space, b->offset), b);
1410
1774
        }
1411
1775
 
 
1776
        buf_flush_list_mutex_enter(buf_pool);
1412
1777
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1413
1778
             b = UT_LIST_GET_NEXT(list, b)) {
1414
1779
                ut_ad(b->in_flush_list);
1436
1801
                }
1437
1802
        }
1438
1803
 
1439
 
        buf_pool_mutex_exit();
 
1804
        buf_flush_list_mutex_exit(buf_pool);
 
1805
        buf_pool_mutex_exit(buf_pool);
 
1806
}
 
1807
 
 
1808
/********************************************************************
 
1809
Determine if a block is a sentinel for a buffer pool watch.
 
1810
@return TRUE if a sentinel for a buffer pool watch, FALSE if not */
 
1811
UNIV_INTERN
 
1812
ibool
 
1813
buf_pool_watch_is_sentinel(
 
1814
/*=======================*/
 
1815
        buf_pool_t*             buf_pool,       /*!< buffer pool instance */
 
1816
        const buf_page_t*       bpage)          /*!< in: block */
 
1817
{
 
1818
        ut_ad(buf_page_in_file(bpage));
 
1819
 
 
1820
        if (bpage < &buf_pool->watch[0]
 
1821
            || bpage >= &buf_pool->watch[BUF_POOL_WATCH_SIZE]) {
 
1822
 
 
1823
                ut_ad(buf_page_get_state(bpage) != BUF_BLOCK_ZIP_PAGE
 
1824
                      || bpage->zip.data != NULL);
 
1825
 
 
1826
                return(FALSE);
 
1827
        }
 
1828
 
 
1829
        ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_PAGE);
 
1830
        ut_ad(!bpage->in_zip_hash);
 
1831
        ut_ad(bpage->in_page_hash);
 
1832
        ut_ad(bpage->zip.data == NULL);
 
1833
        ut_ad(bpage->buf_fix_count > 0);
 
1834
        return(TRUE);
 
1835
}
 
1836
 
 
1837
/****************************************************************//**
 
1838
Add watch for the given page to be read in. Caller must have the buffer pool
 
1839
mutex reserved.
 
1840
@return NULL if watch set, block if the page is in the buffer pool */
 
1841
UNIV_INTERN
 
1842
buf_page_t*
 
1843
buf_pool_watch_set(
 
1844
/*===============*/
 
1845
        ulint   space,  /*!< in: space id */
 
1846
        ulint   offset, /*!< in: page number */
 
1847
        ulint   fold)   /*!< in: buf_page_address_fold(space, offset) */
 
1848
{
 
1849
        buf_page_t*     bpage;
 
1850
        ulint           i;
 
1851
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
1852
 
 
1853
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1854
 
 
1855
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
1856
 
 
1857
        if (UNIV_LIKELY_NULL(bpage)) {
 
1858
                if (!buf_pool_watch_is_sentinel(buf_pool, bpage)) {
 
1859
                        /* The page was loaded meanwhile. */
 
1860
                        return(bpage);
 
1861
                }
 
1862
                /* Add to an existing watch. */
 
1863
                bpage->buf_fix_count++;
 
1864
                return(NULL);
 
1865
        }
 
1866
 
 
1867
        for (i = 0; i < BUF_POOL_WATCH_SIZE; i++) {
 
1868
                bpage = &buf_pool->watch[i];
 
1869
 
 
1870
                ut_ad(bpage->access_time == 0);
 
1871
                ut_ad(bpage->newest_modification == 0);
 
1872
                ut_ad(bpage->oldest_modification == 0);
 
1873
                ut_ad(bpage->zip.data == NULL);
 
1874
                ut_ad(!bpage->in_zip_hash);
 
1875
 
 
1876
                switch (bpage->state) {
 
1877
                case BUF_BLOCK_POOL_WATCH:
 
1878
                        ut_ad(!bpage->in_page_hash);
 
1879
                        ut_ad(bpage->buf_fix_count == 0);
 
1880
 
 
1881
                        /* bpage is pointing to buf_pool->watch[],
 
1882
                        which is protected by buf_pool->mutex.
 
1883
                        Normally, buf_page_t objects are protected by
 
1884
                        buf_block_t::mutex or buf_pool->zip_mutex or both. */
 
1885
 
 
1886
                        bpage->state = BUF_BLOCK_ZIP_PAGE;
 
1887
                        bpage->space = space;
 
1888
                        bpage->offset = offset;
 
1889
                        bpage->buf_fix_count = 1;
 
1890
 
 
1891
                        ut_d(bpage->in_page_hash = TRUE);
 
1892
                        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
1893
                                    fold, bpage);
 
1894
                        return(NULL);
 
1895
                case BUF_BLOCK_ZIP_PAGE:
 
1896
                        ut_ad(bpage->in_page_hash);
 
1897
                        ut_ad(bpage->buf_fix_count > 0);
 
1898
                        break;
 
1899
                default:
 
1900
                        ut_error;
 
1901
                }
 
1902
        }
 
1903
 
 
1904
        /* Allocation failed.  Either the maximum number of purge
 
1905
        threads should never exceed BUF_POOL_WATCH_SIZE, or this code
 
1906
        should be modified to return a special non-NULL value and the
 
1907
        caller should purge the record directly. */
 
1908
        ut_error;
 
1909
 
 
1910
        /* Fix compiler warning */
 
1911
        return(NULL);
 
1912
}
 
1913
 
 
1914
/********************************************************************//**
 
1915
Rebuild buf_pool->page_hash. */
 
1916
static
 
1917
void
 
1918
buf_pool_page_hash_rebuild(void)
 
1919
/*============================*/
 
1920
{
 
1921
        ulint   i;
 
1922
 
 
1923
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1924
                buf_pool_page_hash_rebuild_instance(buf_pool_from_array(i));
 
1925
        }
 
1926
}
 
1927
 
 
1928
/********************************************************************//**
 
1929
Increase the buffer pool size of one buffer pool instance. */
 
1930
static
 
1931
void
 
1932
buf_pool_increase_instance(
 
1933
/*=======================*/
 
1934
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instane */
 
1935
        ulint           change_size)    /*!< in: new size of the pool */
 
1936
{
 
1937
        buf_chunk_t*    chunks;
 
1938
        buf_chunk_t*    chunk;
 
1939
 
 
1940
        buf_pool_mutex_enter(buf_pool);
 
1941
        chunks = static_cast<buf_chunk_t *>(mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks));
 
1942
 
 
1943
        memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks * sizeof *chunks);
 
1944
 
 
1945
        chunk = &chunks[buf_pool->n_chunks];
 
1946
 
 
1947
        if (!buf_chunk_init(buf_pool, chunk, change_size)) {
 
1948
                mem_free(chunks);
 
1949
        } else {
 
1950
                buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1951
                buf_pool->curr_size += chunk->size;
 
1952
                buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1953
                mem_free(buf_pool->chunks);
 
1954
                buf_pool->chunks = chunks;
 
1955
                buf_pool->n_chunks++;
 
1956
        }
 
1957
 
 
1958
        buf_pool_mutex_exit(buf_pool);
 
1959
}
 
1960
 
 
1961
/********************************************************************//**
 
1962
Increase the buffer pool size. */
 
1963
static
 
1964
void
 
1965
buf_pool_increase(
 
1966
/*==============*/
 
1967
        ulint   change_size)
 
1968
{
 
1969
        ulint   i;
 
1970
 
 
1971
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
1972
                buf_pool_increase_instance(
 
1973
                        buf_pool_from_array(i),
 
1974
                        change_size / srv_buf_pool_instances);
 
1975
        }
 
1976
 
 
1977
        buf_pool_set_sizes();
1440
1978
}
1441
1979
 
1442
1980
/********************************************************************//**
1446
1984
buf_pool_resize(void)
1447
1985
/*=================*/
1448
1986
{
1449
 
        buf_pool_mutex_enter();
1450
 
 
1451
 
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
1452
 
 
1453
 
                buf_pool_mutex_exit();
 
1987
        ulint   change_size;
 
1988
        ulint   min_change_size = 1048576 * srv_buf_pool_instances;
 
1989
 
 
1990
        buf_pool_mutex_enter_all();
 
1991
  
 
1992
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
 
1993
  
 
1994
                buf_pool_mutex_exit_all();
 
1995
 
 
1996
                return;
 
1997
 
 
1998
        } else if (srv_buf_pool_curr_size + min_change_size
 
1999
                   > srv_buf_pool_size) {
 
2000
  
 
2001
                change_size = (srv_buf_pool_curr_size - srv_buf_pool_size)
 
2002
                            / UNIV_PAGE_SIZE;
 
2003
 
 
2004
                buf_pool_mutex_exit_all();
 
2005
  
 
2006
                /* Disable adaptive hash indexes and empty the index
 
2007
                in order to free up memory in the buffer pool chunks. */
 
2008
                buf_pool_shrink(change_size);
 
2009
 
 
2010
        } else if (srv_buf_pool_curr_size + min_change_size
 
2011
                   < srv_buf_pool_size) {
 
2012
 
 
2013
                /* Enlarge the buffer pool by at least one megabyte */
 
2014
  
 
2015
                change_size = srv_buf_pool_size - srv_buf_pool_curr_size;
 
2016
 
 
2017
                buf_pool_mutex_exit_all();
 
2018
 
 
2019
                buf_pool_increase(change_size);
 
2020
        } else {
 
2021
                srv_buf_pool_size = srv_buf_pool_old_size;
 
2022
 
 
2023
                buf_pool_mutex_exit_all();
 
2024
 
1454
2025
                return;
1455
2026
        }
1456
 
 
1457
 
        if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
1458
 
 
1459
 
                buf_pool_mutex_exit();
1460
 
 
1461
 
                /* Disable adaptive hash indexes and empty the index
1462
 
                in order to free up memory in the buffer pool chunks. */
1463
 
                buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
1464
 
                                / UNIV_PAGE_SIZE);
1465
 
        } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
1466
 
 
1467
 
                /* Enlarge the buffer pool by at least one megabyte */
1468
 
 
1469
 
                ulint           mem_size
1470
 
                        = srv_buf_pool_size - srv_buf_pool_curr_size;
1471
 
                buf_chunk_t*    chunks;
1472
 
                buf_chunk_t*    chunk;
1473
 
 
1474
 
                chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
1475
 
 
1476
 
                memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
1477
 
                       * sizeof *chunks);
1478
 
 
1479
 
                chunk = &chunks[buf_pool->n_chunks];
1480
 
 
1481
 
                if (!buf_chunk_init(chunk, mem_size)) {
1482
 
                        mem_free(chunks);
1483
 
                } else {
1484
 
                        buf_pool->curr_size += chunk->size;
1485
 
                        srv_buf_pool_curr_size = buf_pool->curr_size
1486
 
                                * UNIV_PAGE_SIZE;
1487
 
                        mem_free(buf_pool->chunks);
1488
 
                        buf_pool->chunks = chunks;
1489
 
                        buf_pool->n_chunks++;
 
2027
  
 
2028
        buf_pool_page_hash_rebuild();
 
2029
}
 
2030
 
 
2031
/****************************************************************//**
 
2032
Remove the sentinel block for the watch before replacing it with a real block.
 
2033
buf_page_watch_clear() or buf_page_watch_occurred() will notice that
 
2034
the block has been replaced with the real block.
 
2035
@return reference count, to be added to the replacement block */
 
2036
static
 
2037
void
 
2038
buf_pool_watch_remove(
 
2039
/*==================*/
 
2040
        buf_pool_t*     buf_pool,       /*!< buffer pool instance */
 
2041
        ulint           fold,           /*!< in: buf_page_address_fold(
 
2042
                                        space, offset) */
 
2043
        buf_page_t*     watch)          /*!< in/out: sentinel for watch */
 
2044
{
 
2045
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2046
 
 
2047
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, watch);
 
2048
        ut_d(watch->in_page_hash = FALSE);
 
2049
        watch->buf_fix_count = 0;
 
2050
        watch->state = BUF_BLOCK_POOL_WATCH;
 
2051
}
 
2052
 
 
2053
/****************************************************************//**
 
2054
Stop watching if the page has been read in.
 
2055
buf_pool_watch_set(space,offset) must have returned NULL before. */
 
2056
UNIV_INTERN
 
2057
void
 
2058
buf_pool_watch_unset(
 
2059
/*=================*/
 
2060
        ulint   space,  /*!< in: space id */
 
2061
        ulint   offset) /*!< in: page number */
 
2062
{
 
2063
        buf_page_t*     bpage;
 
2064
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2065
        ulint           fold = buf_page_address_fold(space, offset);
 
2066
 
 
2067
        buf_pool_mutex_enter(buf_pool);
 
2068
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
2069
        /* The page must exist because buf_pool_watch_set()
 
2070
        increments buf_fix_count. */
 
2071
        ut_a(bpage);
 
2072
 
 
2073
        if (UNIV_UNLIKELY(!buf_pool_watch_is_sentinel(buf_pool, bpage))) {
 
2074
                mutex_t* mutex = buf_page_get_mutex(bpage);
 
2075
 
 
2076
                mutex_enter(mutex);
 
2077
                ut_a(bpage->buf_fix_count > 0);
 
2078
                bpage->buf_fix_count--;
 
2079
                mutex_exit(mutex);
 
2080
        } else {
 
2081
                ut_a(bpage->buf_fix_count > 0);
 
2082
 
 
2083
                if (UNIV_LIKELY(!--bpage->buf_fix_count)) {
 
2084
                        buf_pool_watch_remove(buf_pool, fold, bpage);
1490
2085
                }
1491
 
 
1492
 
                srv_buf_pool_old_size = srv_buf_pool_size;
1493
 
                buf_pool_mutex_exit();
1494
2086
        }
1495
2087
 
1496
 
        buf_pool_page_hash_rebuild();
 
2088
        buf_pool_mutex_exit(buf_pool);
 
2089
}
 
2090
 
 
2091
/****************************************************************//**
 
2092
Check if the page has been read in.
 
2093
This may only be called after buf_pool_watch_set(space,offset)
 
2094
has returned NULL and before invoking buf_pool_watch_unset(space,offset).
 
2095
@return FALSE if the given page was not read in, TRUE if it was */
 
2096
UNIV_INTERN
 
2097
ibool
 
2098
buf_pool_watch_occurred(
 
2099
/*====================*/
 
2100
        ulint   space,  /*!< in: space id */
 
2101
        ulint   offset) /*!< in: page number */
 
2102
{
 
2103
        ibool           ret;
 
2104
        buf_page_t*     bpage;
 
2105
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2106
        ulint           fold    = buf_page_address_fold(space, offset);
 
2107
 
 
2108
        buf_pool_mutex_enter(buf_pool);
 
2109
 
 
2110
        bpage = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
2111
        /* The page must exist because buf_pool_watch_set()
 
2112
        increments buf_fix_count. */
 
2113
        ut_a(bpage);
 
2114
        ret = !buf_pool_watch_is_sentinel(buf_pool, bpage);
 
2115
        buf_pool_mutex_exit(buf_pool);
 
2116
 
 
2117
        return(ret);
1497
2118
}
1498
2119
 
1499
2120
/********************************************************************//**
1506
2127
/*================*/
1507
2128
        buf_page_t*     bpage)  /*!< in: buffer block of a file page */
1508
2129
{
1509
 
        buf_pool_mutex_enter();
 
2130
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
 
2131
 
 
2132
        buf_pool_mutex_enter(buf_pool);
1510
2133
 
1511
2134
        ut_a(buf_page_in_file(bpage));
1512
2135
 
1513
2136
        buf_LRU_make_block_young(bpage);
1514
2137
 
1515
 
        buf_pool_mutex_exit();
 
2138
        buf_pool_mutex_exit(buf_pool);
1516
2139
}
1517
2140
 
1518
2141
/********************************************************************//**
1530
2153
                                        read under mutex protection,
1531
2154
                                        or 0 if unknown */
1532
2155
{
1533
 
        ut_ad(!buf_pool_mutex_own());
 
2156
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
 
2157
 
 
2158
        ut_ad(!buf_pool_mutex_own(buf_pool));
1534
2159
        ut_a(buf_page_in_file(bpage));
1535
2160
 
1536
2161
        if (buf_page_peek_if_too_old(bpage)) {
1537
 
                buf_pool_mutex_enter();
 
2162
                buf_pool_mutex_enter(buf_pool);
1538
2163
                buf_LRU_make_block_young(bpage);
1539
 
                buf_pool_mutex_exit();
 
2164
                buf_pool_mutex_exit(buf_pool);
1540
2165
        } else if (!access_time) {
1541
2166
                ulint   time_ms = ut_time_ms();
1542
 
                buf_pool_mutex_enter();
 
2167
                buf_pool_mutex_enter(buf_pool);
1543
2168
                buf_page_set_accessed(bpage, time_ms);
1544
 
                buf_pool_mutex_exit();
 
2169
                buf_pool_mutex_exit(buf_pool);
1545
2170
        }
1546
2171
}
1547
2172
 
1556
2181
        ulint   offset) /*!< in: page number */
1557
2182
{
1558
2183
        buf_block_t*    block;
1559
 
 
1560
 
        buf_pool_mutex_enter();
1561
 
 
1562
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2184
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2185
 
 
2186
        buf_pool_mutex_enter(buf_pool);
 
2187
 
 
2188
        block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
1563
2189
 
1564
2190
        if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
 
2191
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
1565
2192
                block->check_index_page_at_flush = FALSE;
1566
2193
        }
1567
2194
 
1568
 
        buf_pool_mutex_exit();
 
2195
        buf_pool_mutex_exit(buf_pool);
1569
2196
}
1570
2197
 
1571
2198
/********************************************************************//**
1582
2209
{
1583
2210
        buf_block_t*    block;
1584
2211
        ibool           is_hashed;
1585
 
 
1586
 
        buf_pool_mutex_enter();
1587
 
 
1588
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2212
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2213
 
 
2214
        buf_pool_mutex_enter(buf_pool);
 
2215
 
 
2216
        block = (buf_block_t*) buf_page_hash_get(buf_pool, space, offset);
1589
2217
 
1590
2218
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
1591
2219
                is_hashed = FALSE;
1592
2220
        } else {
 
2221
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
1593
2222
                is_hashed = block->is_hashed;
1594
2223
        }
1595
2224
 
1596
 
        buf_pool_mutex_exit();
 
2225
        buf_pool_mutex_exit(buf_pool);
1597
2226
 
1598
2227
        return(is_hashed);
1599
2228
}
1613
2242
        ulint   offset) /*!< in: page number */
1614
2243
{
1615
2244
        buf_page_t*     bpage;
1616
 
 
1617
 
        buf_pool_mutex_enter();
1618
 
 
1619
 
        bpage = buf_page_hash_get(space, offset);
 
2245
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2246
 
 
2247
        buf_pool_mutex_enter(buf_pool);
 
2248
 
 
2249
        bpage = buf_page_hash_get(buf_pool, space, offset);
1620
2250
 
1621
2251
        if (bpage) {
 
2252
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1622
2253
                bpage->file_page_was_freed = TRUE;
1623
2254
        }
1624
2255
 
1625
 
        buf_pool_mutex_exit();
 
2256
        buf_pool_mutex_exit(buf_pool);
1626
2257
 
1627
2258
        return(bpage);
1628
2259
}
1641
2272
        ulint   offset) /*!< in: page number */
1642
2273
{
1643
2274
        buf_page_t*     bpage;
1644
 
 
1645
 
        buf_pool_mutex_enter();
1646
 
 
1647
 
        bpage = buf_page_hash_get(space, offset);
 
2275
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
 
2276
 
 
2277
        buf_pool_mutex_enter(buf_pool);
 
2278
 
 
2279
        bpage = buf_page_hash_get(buf_pool, space, offset);
1648
2280
 
1649
2281
        if (bpage) {
 
2282
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1650
2283
                bpage->file_page_was_freed = FALSE;
1651
2284
        }
1652
2285
 
1653
 
        buf_pool_mutex_exit();
 
2286
        buf_pool_mutex_exit(buf_pool);
1654
2287
 
1655
2288
        return(bpage);
1656
2289
}
1677
2310
        mutex_t*        block_mutex;
1678
2311
        ibool           must_read;
1679
2312
        unsigned        access_time;
 
2313
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
1680
2314
 
1681
2315
#ifndef UNIV_LOG_DEBUG
1682
2316
        ut_ad(!ibuf_inside());
1684
2318
        buf_pool->stat.n_page_gets++;
1685
2319
 
1686
2320
        for (;;) {
1687
 
                buf_pool_mutex_enter();
 
2321
                buf_pool_mutex_enter(buf_pool);
1688
2322
lookup:
1689
 
                bpage = buf_page_hash_get(space, offset);
 
2323
                bpage = buf_page_hash_get(buf_pool, space, offset);
1690
2324
                if (bpage) {
 
2325
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
1691
2326
                        break;
1692
2327
                }
1693
2328
 
1694
2329
                /* Page not in buf_pool: needs to be read from file */
1695
2330
 
1696
 
                buf_pool_mutex_exit();
 
2331
                buf_pool_mutex_exit(buf_pool);
1697
2332
 
1698
2333
                buf_read_page(space, zip_size, offset);
1699
2334
 
1705
2340
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
1706
2341
                /* There is no compressed page. */
1707
2342
err_exit:
1708
 
                buf_pool_mutex_exit();
 
2343
                buf_pool_mutex_exit(buf_pool);
1709
2344
                return(NULL);
1710
2345
        }
1711
2346
 
 
2347
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
 
2348
 
1712
2349
        switch (buf_page_get_state(bpage)) {
1713
2350
        case BUF_BLOCK_NOT_USED:
1714
2351
        case BUF_BLOCK_READY_FOR_USE:
1718
2355
                break;
1719
2356
        case BUF_BLOCK_ZIP_PAGE:
1720
2357
        case BUF_BLOCK_ZIP_DIRTY:
1721
 
                block_mutex = &buf_pool_zip_mutex;
 
2358
                block_mutex = &buf_pool->zip_mutex;
1722
2359
                mutex_enter(block_mutex);
1723
2360
                bpage->buf_fix_count++;
1724
2361
                goto got_block;
1746
2383
        must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
1747
2384
        access_time = buf_page_is_accessed(bpage);
1748
2385
 
1749
 
        buf_pool_mutex_exit();
 
2386
        buf_pool_mutex_exit(buf_pool);
1750
2387
 
1751
2388
        mutex_exit(block_mutex);
1752
2389
 
1818
2455
        buf_block_t*    block,  /*!< in/out: block */
1819
2456
        ibool           check)  /*!< in: TRUE=verify the page checksum */
1820
2457
{
1821
 
        const byte* frame = block->page.zip.data;
 
2458
        const byte*     frame           = block->page.zip.data;
 
2459
        ulint           stamp_checksum  = mach_read_from_4(
 
2460
                frame + FIL_PAGE_SPACE_OR_CHKSUM);
1822
2461
 
1823
2462
        ut_ad(buf_block_get_zip_size(block));
1824
2463
        ut_a(buf_block_get_space(block) != 0);
1825
2464
 
1826
 
        if (UNIV_LIKELY(check)) {
1827
 
                ulint   stamp_checksum  = mach_read_from_4(
1828
 
                        frame + FIL_PAGE_SPACE_OR_CHKSUM);
 
2465
        if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
1829
2466
                ulint   calc_checksum   = page_zip_calc_checksum(
1830
2467
                        frame, page_zip_get_size(&block->page.zip));
1831
2468
 
1876
2513
 
1877
2514
#ifndef UNIV_HOTBACKUP
1878
2515
/*******************************************************************//**
1879
 
Gets the block to whose frame the pointer is pointing to.
1880
 
@return pointer to block, never NULL */
1881
 
UNIV_INTERN
 
2516
Gets the block to whose frame the pointer is pointing to if found
 
2517
in this buffer pool instance.
 
2518
@return pointer to block */
 
2519
static
1882
2520
buf_block_t*
1883
 
buf_block_align(
1884
 
/*============*/
1885
 
        const byte*     ptr)    /*!< in: pointer to a frame */
 
2521
buf_block_align_instance(
 
2522
/*=====================*/
 
2523
        buf_pool_t*     buf_pool,       /*!< in: buffer in which the block
 
2524
                                        resides */
 
2525
        const byte*     ptr)            /*!< in: pointer to a frame */
1886
2526
{
1887
2527
        buf_chunk_t*    chunk;
1888
2528
        ulint           i;
1908
2548
                        ut_ad(block->frame == page_align(ptr));
1909
2549
#ifdef UNIV_DEBUG
1910
2550
                        /* A thread that updates these fields must
1911
 
                        hold buf_pool_mutex and block->mutex.  Acquire
 
2551
                        hold buf_pool->mutex and block->mutex.  Acquire
1912
2552
                        only the latter. */
1913
2553
                        mutex_enter(&block->mutex);
1914
2554
 
1957
2597
                }
1958
2598
        }
1959
2599
 
 
2600
        return(NULL);
 
2601
}
 
2602
 
 
2603
/*******************************************************************//**
 
2604
Gets the block to whose frame the pointer is pointing to.
 
2605
@return pointer to block, never NULL */
 
2606
UNIV_INTERN
 
2607
buf_block_t*
 
2608
buf_block_align(
 
2609
/*============*/
 
2610
        const byte*     ptr)    /*!< in: pointer to a frame */
 
2611
{
 
2612
        ulint           i;
 
2613
 
 
2614
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
2615
                buf_block_t*    block;
 
2616
 
 
2617
                block = buf_block_align_instance(
 
2618
                        buf_pool_from_array(i), ptr);
 
2619
                if (block) {
 
2620
                        return(block);
 
2621
                }
 
2622
        }
 
2623
 
1960
2624
        /* The block should always be found. */
1961
2625
        ut_error;
1962
2626
        return(NULL);
1964
2628
 
1965
2629
/********************************************************************//**
1966
2630
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
1967
 
the buf_block_t itself or a member of it
 
2631
the buf_block_t itself or a member of it. This functions checks one of
 
2632
the buffer pool instances.
1968
2633
@return TRUE if ptr belongs to a buf_block_t struct */
1969
 
UNIV_INTERN
 
2634
static
1970
2635
ibool
1971
 
buf_pointer_is_block_field(
1972
 
/*=======================*/
1973
 
        const void*             ptr)    /*!< in: pointer not
1974
 
                                        dereferenced */
 
2636
buf_pointer_is_block_field_instance(
 
2637
/*================================*/
 
2638
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
2639
        const void*     ptr)            /*!< in: pointer not dereferenced */
1975
2640
{
1976
2641
        const buf_chunk_t*              chunk   = buf_pool->chunks;
1977
2642
        const buf_chunk_t* const        echunk  = chunk + buf_pool->n_chunks;
1992
2657
}
1993
2658
 
1994
2659
/********************************************************************//**
 
2660
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
 
2661
the buf_block_t itself or a member of it
 
2662
@return TRUE if ptr belongs to a buf_block_t struct */
 
2663
UNIV_INTERN
 
2664
ibool
 
2665
buf_pointer_is_block_field(
 
2666
/*=======================*/
 
2667
        const void*     ptr)    /*!< in: pointer not dereferenced */
 
2668
{
 
2669
        ulint   i;
 
2670
 
 
2671
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
2672
                ibool   found;
 
2673
 
 
2674
                found = buf_pointer_is_block_field_instance(
 
2675
                        buf_pool_from_array(i), ptr);
 
2676
                if (found) {
 
2677
                        return(TRUE);
 
2678
                }
 
2679
        }
 
2680
 
 
2681
        return(FALSE);
 
2682
}
 
2683
 
 
2684
/********************************************************************//**
1995
2685
Find out if a buffer block was created by buf_chunk_init().
1996
2686
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
1997
2687
static
1998
2688
ibool
1999
2689
buf_block_is_uncompressed(
2000
2690
/*======================*/
2001
 
        const buf_block_t*      block)  /*!< in: pointer to block,
2002
 
                                        not dereferenced */
 
2691
        buf_pool_t*             buf_pool,       /*!< in: buffer pool instance */
 
2692
        const buf_block_t*      block)          /*!< in: pointer to block,
 
2693
                                                not dereferenced */
2003
2694
{
2004
 
        ut_ad(buf_pool_mutex_own());
 
2695
        ut_ad(buf_pool_mutex_own(buf_pool));
2005
2696
 
2006
2697
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2007
2698
                /* The pointer should be aligned. */
2008
2699
                return(FALSE);
2009
2700
        }
2010
2701
 
2011
 
        return(buf_pointer_is_block_field((void *)block));
 
2702
        return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
2012
2703
}
2013
2704
 
2014
2705
/********************************************************************//**
2025
2716
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2026
2717
        buf_block_t*    guess,  /*!< in: guessed block or NULL */
2027
2718
        ulint           mode,   /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2028
 
                                BUF_GET_NO_LATCH */
 
2719
                                BUF_GET_NO_LATCH, or
 
2720
                                BUF_GET_IF_IN_POOL_OR_WATCH */
2029
2721
        const char*     file,   /*!< in: file name */
2030
2722
        ulint           line,   /*!< in: line where called */
2031
2723
        mtr_t*          mtr)    /*!< in: mini-transaction */
2032
2724
{
2033
2725
        buf_block_t*    block;
 
2726
        ulint           fold;
2034
2727
        unsigned        access_time;
2035
2728
        ulint           fix_type;
2036
2729
        ibool           must_read;
 
2730
        ulint           retries = 0;
 
2731
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2037
2732
 
2038
2733
        ut_ad(mtr);
 
2734
        ut_ad(mtr->state == MTR_ACTIVE);
2039
2735
        ut_ad((rw_latch == RW_S_LATCH)
2040
2736
              || (rw_latch == RW_X_LATCH)
2041
2737
              || (rw_latch == RW_NO_LATCH));
2042
2738
        ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_NO_LATCH));
2043
 
        ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
2044
 
              || (mode == BUF_GET_NO_LATCH));
 
2739
        ut_ad(mode == BUF_GET
 
2740
              || mode == BUF_GET_IF_IN_POOL
 
2741
              || mode == BUF_GET_NO_LATCH
 
2742
              || mode == BUF_GET_IF_IN_POOL_OR_WATCH);
2045
2743
        ut_ad(zip_size == fil_space_get_zip_size(space));
2046
2744
        ut_ad(ut_is_2pow(zip_size));
2047
2745
#ifndef UNIV_LOG_DEBUG
2048
2746
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2049
2747
#endif
2050
2748
        buf_pool->stat.n_page_gets++;
 
2749
        fold = buf_page_address_fold(space, offset);
2051
2750
loop:
2052
2751
        block = guess;
2053
 
        buf_pool_mutex_enter();
 
2752
        buf_pool_mutex_enter(buf_pool);
2054
2753
 
2055
2754
        if (block) {
2056
2755
                /* If the guess is a compressed page descriptor that
2061
2760
                the guess may be pointing to a buffer pool chunk that
2062
2761
                has been released when resizing the buffer pool. */
2063
2762
 
2064
 
                if (!buf_block_is_uncompressed(block)
 
2763
                if (!buf_block_is_uncompressed(buf_pool, block)
2065
2764
                    || offset != block->page.offset
2066
2765
                    || space != block->page.space
2067
2766
                    || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2074
2773
        }
2075
2774
 
2076
2775
        if (block == NULL) {
2077
 
                block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2776
                block = (buf_block_t*) buf_page_hash_get_low(
 
2777
                        buf_pool, space, offset, fold);
2078
2778
        }
2079
2779
 
2080
2780
loop2:
 
2781
        if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
 
2782
                block = NULL;
 
2783
        }
 
2784
 
2081
2785
        if (block == NULL) {
2082
2786
                /* Page not in buf_pool: needs to be read from file */
2083
2787
 
2084
 
                buf_pool_mutex_exit();
2085
 
 
2086
 
                if (mode == BUF_GET_IF_IN_POOL) {
 
2788
                if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
 
2789
                        block = (buf_block_t*) buf_pool_watch_set(
 
2790
                                space, offset, fold);
 
2791
 
 
2792
                        if (UNIV_LIKELY_NULL(block)) {
 
2793
 
 
2794
                                goto got_block;
 
2795
                        }
 
2796
                }
 
2797
 
 
2798
                buf_pool_mutex_exit(buf_pool);
 
2799
 
 
2800
                if (mode == BUF_GET_IF_IN_POOL
 
2801
                    || mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
2087
2802
 
2088
2803
                        return(NULL);
2089
2804
                }
2090
2805
 
2091
 
                buf_read_page(space, zip_size, offset);
 
2806
                if (buf_read_page(space, zip_size, offset)) {
 
2807
                        retries = 0;
 
2808
                } else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
 
2809
                        ++retries;
 
2810
                } else {
 
2811
                        fprintf(stderr, "InnoDB: Error: Unable"
 
2812
                                " to read tablespace %lu page no"
 
2813
                                " %lu into the buffer pool after"
 
2814
                                " %lu attempts\n"
 
2815
                                "InnoDB: The most probable cause"
 
2816
                                " of this error may be that the"
 
2817
                                " table has been corrupted.\n"
 
2818
                                "InnoDB: You can try to fix this"
 
2819
                                " problem by using"
 
2820
                                " innodb_force_recovery.\n"
 
2821
                                "InnoDB: Please see reference manual"
 
2822
                                " for more details.\n"
 
2823
                                "InnoDB: Aborting...\n",
 
2824
                                space, offset,
 
2825
                                BUF_PAGE_READ_MAX_RETRIES);
 
2826
 
 
2827
                        ut_error;
 
2828
                }
2092
2829
 
2093
2830
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2094
2831
                ut_a(++buf_dbg_counter % 37 || buf_validate());
2096
2833
                goto loop;
2097
2834
        }
2098
2835
 
 
2836
got_block:
2099
2837
        ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
2100
2838
 
2101
2839
        must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
2102
2840
 
2103
2841
        if (must_read && mode == BUF_GET_IF_IN_POOL) {
2104
 
                /* The page is only being read to buffer */
2105
 
                buf_pool_mutex_exit();
 
2842
 
 
2843
                /* The page is being read to buffer pool,
 
2844
                but we cannot wait around for the read to
 
2845
                complete. */
 
2846
                buf_pool_mutex_exit(buf_pool);
2106
2847
 
2107
2848
                return(NULL);
2108
2849
        }
2118
2859
        case BUF_BLOCK_ZIP_DIRTY:
2119
2860
                bpage = &block->page;
2120
2861
                /* Protect bpage->buf_fix_count. */
2121
 
                mutex_enter(&buf_pool_zip_mutex);
 
2862
                mutex_enter(&buf_pool->zip_mutex);
2122
2863
 
2123
2864
                if (bpage->buf_fix_count
2124
2865
                    || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2125
2866
                        /* This condition often occurs when the buffer
2126
2867
                        is not buffer-fixed, but I/O-fixed by
2127
2868
                        buf_page_init_for_read(). */
2128
 
                        mutex_exit(&buf_pool_zip_mutex);
 
2869
                        mutex_exit(&buf_pool->zip_mutex);
2129
2870
wait_until_unfixed:
2130
2871
                        /* The block is buffer-fixed or I/O-fixed.
2131
2872
                        Try again later. */
2132
 
                        buf_pool_mutex_exit();
 
2873
                        buf_pool_mutex_exit(buf_pool);
2133
2874
                        os_thread_sleep(WAIT_FOR_READ);
2134
 
 
 
2875
  
2135
2876
                        goto loop;
2136
2877
                }
2137
2878
 
2138
2879
                /* Allocate an uncompressed page. */
2139
 
                buf_pool_mutex_exit();
2140
 
                mutex_exit(&buf_pool_zip_mutex);
 
2880
                buf_pool_mutex_exit(buf_pool);
 
2881
                mutex_exit(&buf_pool->zip_mutex);
2141
2882
 
2142
 
                block = buf_LRU_get_free_block(0);
 
2883
                block = buf_LRU_get_free_block(buf_pool, 0);
2143
2884
                ut_a(block);
2144
2885
 
2145
 
                buf_pool_mutex_enter();
 
2886
                buf_pool_mutex_enter(buf_pool);
2146
2887
                mutex_enter(&block->mutex);
2147
2888
 
2148
2889
                {
2149
 
                        buf_page_t*     hash_bpage
2150
 
                                = buf_page_hash_get(space, offset);
 
2890
                        buf_page_t*     hash_bpage;
 
2891
 
 
2892
                        hash_bpage = buf_page_hash_get_low(
 
2893
                                buf_pool, space, offset, fold);
2151
2894
 
2152
2895
                        if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2153
2896
                                /* The buf_pool->page_hash was modified
2154
 
                                while buf_pool_mutex was released.
 
2897
                                while buf_pool->mutex was released.
2155
2898
                                Free the block that was allocated. */
2156
2899
 
2157
2900
                                buf_LRU_block_free_non_file_page(block);
2167
2910
                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
2168
2911
 
2169
2912
                        /* The block was buffer-fixed or I/O-fixed
2170
 
                        while buf_pool_mutex was not held by this thread.
 
2913
                        while buf_pool->mutex was not held by this thread.
2171
2914
                        Free the block that was allocated and try again.
2172
2915
                        This should be extremely unlikely. */
2173
2916
 
2180
2923
                /* Move the compressed page from bpage to block,
2181
2924
                and uncompress it. */
2182
2925
 
2183
 
                mutex_enter(&buf_pool_zip_mutex);
 
2926
                mutex_enter(&buf_pool->zip_mutex);
2184
2927
 
2185
2928
                buf_relocate(bpage, &block->page);
2186
2929
                buf_block_init_low(block);
2196
2939
                        ut_ad(!block->page.in_flush_list);
2197
2940
                } else {
2198
2941
                        /* Relocate buf_pool->flush_list. */
2199
 
                        buf_page_t*     b;
2200
 
 
2201
 
                        b = UT_LIST_GET_PREV(list, &block->page);
2202
 
                        ut_ad(block->page.in_flush_list);
2203
 
                        UT_LIST_REMOVE(list, buf_pool->flush_list,
2204
 
                                       &block->page);
2205
 
 
2206
 
                        if (b) {
2207
 
                                UT_LIST_INSERT_AFTER(
2208
 
                                        list, buf_pool->flush_list, b,
2209
 
                                        &block->page);
2210
 
                        } else {
2211
 
                                UT_LIST_ADD_FIRST(
2212
 
                                        list, buf_pool->flush_list,
2213
 
                                        &block->page);
2214
 
                        }
 
2942
                        buf_flush_relocate_on_flush_list(bpage,
 
2943
                                                         &block->page);
2215
2944
                }
2216
2945
 
2217
2946
                /* Buffer-fix, I/O-fix, and X-latch the block
2224
2953
 
2225
2954
                block->page.buf_fix_count = 1;
2226
2955
                buf_block_set_io_fix(block, BUF_IO_READ);
2227
 
                rw_lock_x_lock(&block->lock);
 
2956
                rw_lock_x_lock_func(&block->lock, 0, file, line);
 
2957
 
 
2958
                UNIV_MEM_INVALID(bpage, sizeof *bpage);
 
2959
 
2228
2960
                mutex_exit(&block->mutex);
2229
 
                mutex_exit(&buf_pool_zip_mutex);
 
2961
                mutex_exit(&buf_pool->zip_mutex);
2230
2962
                buf_pool->n_pend_unzip++;
2231
2963
 
2232
 
                buf_buddy_free(bpage, sizeof *bpage);
 
2964
                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
2233
2965
 
2234
 
                buf_pool_mutex_exit();
 
2966
                buf_pool_mutex_exit(buf_pool);
2235
2967
 
2236
2968
                /* Decompress the page and apply buffered operations
2237
 
                while not holding buf_pool_mutex or block->mutex. */
 
2969
                while not holding buf_pool->mutex or block->mutex. */
2238
2970
                success = buf_zip_decompress(block, srv_use_checksums);
 
2971
                ut_a(success);
2239
2972
 
2240
 
                if (UNIV_LIKELY(success)) {
 
2973
                if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
2241
2974
                        ibuf_merge_or_delete_for_page(block, space, offset,
2242
2975
                                                      zip_size, TRUE);
2243
2976
                }
2244
2977
 
2245
2978
                /* Unfix and unlatch the block. */
2246
 
                buf_pool_mutex_enter();
 
2979
                buf_pool_mutex_enter(buf_pool);
2247
2980
                mutex_enter(&block->mutex);
2248
2981
                block->page.buf_fix_count--;
2249
2982
                buf_block_set_io_fix(block, BUF_IO_NONE);
2251
2984
                buf_pool->n_pend_unzip--;
2252
2985
                rw_lock_x_unlock(&block->lock);
2253
2986
 
2254
 
                if (UNIV_UNLIKELY(!success)) {
2255
 
 
2256
 
                        buf_pool_mutex_exit();
2257
 
                        return(NULL);
2258
 
                }
2259
 
 
2260
2987
                break;
2261
2988
 
2262
2989
        case BUF_BLOCK_ZIP_FREE:
2271
2998
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2272
2999
 
2273
3000
        mutex_enter(&block->mutex);
 
3001
#if UNIV_WORD_SIZE == 4
 
3002
        /* On 32-bit systems, there is no padding in buf_page_t.  On
 
3003
        other systems, Valgrind could complain about uninitialized pad
 
3004
        bytes. */
2274
3005
        UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
 
3006
#endif
 
3007
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
 
3008
        if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
 
3009
            && ibuf_debug) {
 
3010
                /* Try to evict the block from the buffer pool, to use the
 
3011
                insert buffer (change buffer) as much as possible. */
 
3012
 
 
3013
                if (buf_LRU_free_block(&block->page, TRUE, NULL)
 
3014
                    == BUF_LRU_FREED) {
 
3015
                        mutex_exit(&block->mutex);
 
3016
                        if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
 
3017
                                /* Set the watch, as it would have
 
3018
                                been set if the page were not in the
 
3019
                                buffer pool in the first place. */
 
3020
                                block = (buf_block_t*) buf_pool_watch_set(
 
3021
                                        space, offset, fold);
 
3022
 
 
3023
                                if (UNIV_LIKELY_NULL(block)) {
 
3024
 
 
3025
                                        /* The page entered the buffer
 
3026
                                        pool for some reason. Try to
 
3027
                                        evict it again. */
 
3028
                                        goto got_block;
 
3029
                                }
 
3030
                        }
 
3031
                        buf_pool_mutex_exit(buf_pool);
 
3032
                        fprintf(stderr,
 
3033
                                "innodb_change_buffering_debug evict %u %u\n",
 
3034
                                (unsigned) space, (unsigned) offset);
 
3035
                        return(NULL);
 
3036
                } else if (buf_flush_page_try(buf_pool, block)) {
 
3037
                        fprintf(stderr,
 
3038
                                "innodb_change_buffering_debug flush %u %u\n",
 
3039
                                (unsigned) space, (unsigned) offset);
 
3040
                        guess = block;
 
3041
                        goto loop;
 
3042
                }
 
3043
 
 
3044
                /* Failed to evict the page; change it directly */
 
3045
        }
 
3046
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
2275
3047
 
2276
3048
        buf_block_buf_fix_inc(block, file, line);
2277
3049
 
2281
3053
 
2282
3054
        access_time = buf_page_is_accessed(&block->page);
2283
3055
 
2284
 
        buf_pool_mutex_exit();
 
3056
        buf_pool_mutex_exit(buf_pool);
2285
3057
 
2286
3058
        buf_page_set_accessed_make_young(&block->page, access_time);
2287
3059
 
2356
3128
@return TRUE if success */
2357
3129
UNIV_INTERN
2358
3130
ibool
2359
 
buf_page_optimistic_get_func(
2360
 
/*=========================*/
 
3131
buf_page_optimistic_get(
 
3132
/*====================*/
2361
3133
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
2362
3134
        buf_block_t*    block,  /*!< in: guessed buffer block */
2363
3135
        ib_uint64_t     modify_clock,/*!< in: modify clock value if mode is
2366
3138
        ulint           line,   /*!< in: line where called */
2367
3139
        mtr_t*          mtr)    /*!< in: mini-transaction */
2368
3140
{
 
3141
        buf_pool_t*     buf_pool;
2369
3142
        unsigned        access_time;
2370
3143
        ibool           success;
2371
3144
        ulint           fix_type;
2372
3145
 
2373
 
        ut_ad(mtr && block);
 
3146
        ut_ad(block);
 
3147
        ut_ad(mtr);
 
3148
        ut_ad(mtr->state == MTR_ACTIVE);
2374
3149
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
2375
3150
 
2376
3151
        mutex_enter(&block->mutex);
2457
3232
        ut_a(ibuf_count_get(buf_block_get_space(block),
2458
3233
                            buf_block_get_page_no(block)) == 0);
2459
3234
#endif
 
3235
        buf_pool = buf_pool_from_block(block);
2460
3236
        buf_pool->stat.n_page_gets++;
2461
3237
 
2462
3238
        return(TRUE);
2478
3254
        ulint           line,   /*!< in: line where called */
2479
3255
        mtr_t*          mtr)    /*!< in: mini-transaction */
2480
3256
{
 
3257
        buf_pool_t*     buf_pool;
2481
3258
        ibool           success;
2482
3259
        ulint           fix_type;
2483
3260
 
2484
3261
        ut_ad(mtr);
 
3262
        ut_ad(mtr->state == MTR_ACTIVE);
2485
3263
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
2486
3264
 
2487
3265
        mutex_enter(&block->mutex);
2505
3283
 
2506
3284
        mutex_exit(&block->mutex);
2507
3285
 
 
3286
        buf_pool = buf_pool_from_block(block);
 
3287
 
2508
3288
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
2509
 
                buf_pool_mutex_enter();
 
3289
                buf_pool_mutex_enter(buf_pool);
2510
3290
                buf_LRU_make_block_young(&block->page);
2511
 
                buf_pool_mutex_exit();
 
3291
                buf_pool_mutex_exit(buf_pool);
2512
3292
        } else if (!buf_page_is_accessed(&block->page)) {
2513
3293
                /* Above, we do a dirty read on purpose, to avoid
2514
3294
                mutex contention.  The field buf_page_t::access_time
2516
3296
                field must be protected by mutex, however. */
2517
3297
                ulint   time_ms = ut_time_ms();
2518
3298
 
2519
 
                buf_pool_mutex_enter();
 
3299
                buf_pool_mutex_enter(buf_pool);
2520
3300
                buf_page_set_accessed(&block->page, time_ms);
2521
 
                buf_pool_mutex_exit();
 
3301
                buf_pool_mutex_exit(buf_pool);
2522
3302
        }
2523
3303
 
2524
3304
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
2580
3360
        buf_block_t*    block;
2581
3361
        ibool           success;
2582
3362
        ulint           fix_type;
2583
 
 
2584
 
        buf_pool_mutex_enter();
2585
 
        block = buf_block_hash_get(space_id, page_no);
2586
 
 
2587
 
        if (!block) {
2588
 
                buf_pool_mutex_exit();
 
3363
        buf_pool_t*     buf_pool = buf_pool_get(space_id, page_no);
 
3364
 
 
3365
        ut_ad(mtr);
 
3366
        ut_ad(mtr->state == MTR_ACTIVE);
 
3367
 
 
3368
        buf_pool_mutex_enter(buf_pool);
 
3369
        block = buf_block_hash_get(buf_pool, space_id, page_no);
 
3370
 
 
3371
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
 
3372
                buf_pool_mutex_exit(buf_pool);
2589
3373
                return(NULL);
2590
3374
        }
2591
3375
 
 
3376
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
 
3377
 
2592
3378
        mutex_enter(&block->mutex);
2593
 
        buf_pool_mutex_exit();
 
3379
        buf_pool_mutex_exit(buf_pool);
2594
3380
 
2595
3381
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2596
3382
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2673
3459
        ulint           space,  /*!< in: space id */
2674
3460
        ulint           offset, /*!< in: offset of the page within space
2675
3461
                                in units of a page */
 
3462
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
2676
3463
        buf_block_t*    block)  /*!< in: block to init */
2677
3464
{
2678
3465
        buf_page_t*     hash_page;
 
3466
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2679
3467
 
2680
 
        ut_ad(buf_pool_mutex_own());
 
3468
        ut_ad(buf_pool_mutex_own(buf_pool));
2681
3469
        ut_ad(mutex_own(&(block->mutex)));
2682
3470
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
2683
3471
 
2695
3483
 
2696
3484
        buf_block_init_low(block);
2697
3485
 
2698
 
        block->lock_hash_val    = lock_rec_hash(space, offset);
 
3486
        block->lock_hash_val = lock_rec_hash(space, offset);
 
3487
 
 
3488
        buf_page_init_low(&block->page);
2699
3489
 
2700
3490
        /* Insert into the hash table of file pages */
2701
3491
 
2702
 
        hash_page = buf_page_hash_get(space, offset);
2703
 
 
2704
 
        if (UNIV_LIKELY_NULL(hash_page)) {
 
3492
        hash_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
3493
 
 
3494
        if (UNIV_LIKELY(!hash_page)) {
 
3495
        } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) {
 
3496
                /* Preserve the reference count. */
 
3497
                ulint   buf_fix_count = hash_page->buf_fix_count;
 
3498
 
 
3499
                ut_a(buf_fix_count > 0);
 
3500
                block->page.buf_fix_count += buf_fix_count;
 
3501
                buf_pool_watch_remove(buf_pool, fold, hash_page);
 
3502
        } else {
2705
3503
                fprintf(stderr,
2706
3504
                        "InnoDB: Error: page %lu %lu already found"
2707
3505
                        " in the hash table: %p, %p\n",
2710
3508
                        (const void*) hash_page, (const void*) block);
2711
3509
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2712
3510
                mutex_exit(&block->mutex);
2713
 
                buf_pool_mutex_exit();
 
3511
                buf_pool_mutex_exit(buf_pool);
2714
3512
                buf_print();
2715
3513
                buf_LRU_print();
2716
3514
                buf_validate();
2719
3517
                ut_error;
2720
3518
        }
2721
3519
 
2722
 
        buf_page_init_low(&block->page);
2723
 
 
2724
3520
        ut_ad(!block->page.in_zip_hash);
2725
3521
        ut_ad(!block->page.in_page_hash);
2726
3522
        ut_d(block->page.in_page_hash = TRUE);
2727
3523
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2728
 
                    buf_page_address_fold(space, offset), &block->page);
 
3524
                    fold, &block->page);
2729
3525
}
2730
3526
 
2731
3527
/********************************************************************//**
2747
3543
        ulint           space,  /*!< in: space id */
2748
3544
        ulint           zip_size,/*!< in: compressed page size, or 0 */
2749
3545
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
2750
 
        ib_int64_t      tablespace_version,/*!< in: prevents reading from a wrong
 
3546
        ib_int64_t      tablespace_version,
 
3547
                                /*!< in: prevents reading from a wrong
2751
3548
                                version of the tablespace in case we have done
2752
3549
                                DISCARD + IMPORT */
2753
3550
        ulint           offset) /*!< in: page number */
2754
3551
{
2755
3552
        buf_block_t*    block;
2756
 
        buf_page_t*     bpage;
 
3553
        buf_page_t*     bpage   = NULL;
 
3554
        buf_page_t*     watch_page;
2757
3555
        mtr_t           mtr;
 
3556
        ulint           fold;
2758
3557
        ibool           lru     = FALSE;
2759
3558
        void*           data;
 
3559
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2760
3560
 
2761
3561
        ut_ad(buf_pool);
2762
3562
 
2785
3585
            && UNIV_LIKELY(!recv_recovery_is_on())) {
2786
3586
                block = NULL;
2787
3587
        } else {
2788
 
                block = buf_LRU_get_free_block(0);
 
3588
                block = buf_LRU_get_free_block(buf_pool, 0);
2789
3589
                ut_ad(block);
 
3590
                ut_ad(buf_pool_from_block(block) == buf_pool);
2790
3591
        }
2791
3592
 
2792
 
        buf_pool_mutex_enter();
2793
 
 
2794
 
        if (buf_page_hash_get(space, offset)) {
 
3593
        fold = buf_page_address_fold(space, offset);
 
3594
 
 
3595
        buf_pool_mutex_enter(buf_pool);
 
3596
 
 
3597
        watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
 
3598
        if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
2795
3599
                /* The page is already in the buffer pool. */
 
3600
                watch_page = NULL;
2796
3601
err_exit:
2797
3602
                if (block) {
2798
3603
                        mutex_enter(&block->mutex);
2816
3621
        if (block) {
2817
3622
                bpage = &block->page;
2818
3623
                mutex_enter(&block->mutex);
2819
 
                buf_page_init(space, offset, block);
 
3624
 
 
3625
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
 
3626
 
 
3627
                buf_page_init(space, offset, fold, block);
2820
3628
 
2821
3629
                /* The block must be put to the LRU list, to the old blocks */
2822
3630
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2836
3644
                if (UNIV_UNLIKELY(zip_size)) {
2837
3645
                        page_zip_set_size(&block->page.zip, zip_size);
2838
3646
 
2839
 
                        /* buf_pool_mutex may be released and
 
3647
                        /* buf_pool->mutex may be released and
2840
3648
                        reacquired by buf_buddy_alloc().  Thus, we
2841
3649
                        must release block->mutex in order not to
2842
3650
                        break the latching order in the reacquisition
2843
 
                        of buf_pool_mutex.  We also must defer this
 
3651
                        of buf_pool->mutex.  We also must defer this
2844
3652
                        operation until after the block descriptor has
2845
3653
                        been added to buf_pool->LRU and
2846
3654
                        buf_pool->page_hash. */
2847
3655
                        mutex_exit(&block->mutex);
2848
 
                        data = buf_buddy_alloc(zip_size, &lru);
 
3656
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
2849
3657
                        mutex_enter(&block->mutex);
2850
 
                        block->page.zip.data = data;
 
3658
                        block->page.zip.data = static_cast<unsigned char *>(data);
2851
3659
 
2852
3660
                        /* To maintain the invariant
2853
3661
                        block->in_unzip_LRU_list
2869
3677
                control block (bpage), in order to avoid the
2870
3678
                invocation of buf_buddy_relocate_block() on
2871
3679
                uninitialized data. */
2872
 
                data = buf_buddy_alloc(zip_size, &lru);
2873
 
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
 
3680
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
3681
                bpage = static_cast<buf_page_struct *>(buf_buddy_alloc(buf_pool, sizeof *bpage, &lru));
 
3682
 
 
3683
                /* Initialize the buf_pool pointer. */
 
3684
                bpage->buf_pool_index = buf_pool_index(buf_pool);
2874
3685
 
2875
3686
                /* If buf_buddy_alloc() allocated storage from the LRU list,
2876
 
                it released and reacquired buf_pool_mutex.  Thus, we must
 
3687
                it released and reacquired buf_pool->mutex.  Thus, we must
2877
3688
                check the page_hash again, as it may have been modified. */
2878
 
                if (UNIV_UNLIKELY(lru)
2879
 
                    && UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
2880
 
 
2881
 
                        /* The block was added by some other thread. */
2882
 
                        buf_buddy_free(bpage, sizeof *bpage);
2883
 
                        buf_buddy_free(data, zip_size);
2884
 
 
2885
 
                        bpage = NULL;
2886
 
                        goto func_exit;
 
3689
                if (UNIV_UNLIKELY(lru)) {
 
3690
 
 
3691
                        watch_page = buf_page_hash_get_low(
 
3692
                                buf_pool, space, offset, fold);
 
3693
 
 
3694
                        if (watch_page
 
3695
                            && !buf_pool_watch_is_sentinel(buf_pool,
 
3696
                                                           watch_page)) {
 
3697
 
 
3698
                                /* The block was added by some other thread. */
 
3699
                                watch_page = NULL;
 
3700
                                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 
3701
                                buf_buddy_free(buf_pool, data, zip_size);
 
3702
 
 
3703
                                bpage = NULL;
 
3704
                                goto func_exit;
 
3705
                        }
2887
3706
                }
2888
3707
 
2889
3708
                page_zip_des_init(&bpage->zip);
2890
3709
                page_zip_set_size(&bpage->zip, zip_size);
2891
 
                bpage->zip.data = data;
 
3710
                bpage->zip.data = static_cast<unsigned char *>(data);
2892
3711
 
2893
 
                mutex_enter(&buf_pool_zip_mutex);
 
3712
                mutex_enter(&buf_pool->zip_mutex);
2894
3713
                UNIV_MEM_DESC(bpage->zip.data,
2895
3714
                              page_zip_get_size(&bpage->zip), bpage);
 
3715
 
2896
3716
                buf_page_init_low(bpage);
 
3717
 
2897
3718
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
2898
3719
                bpage->space    = space;
2899
3720
                bpage->offset   = offset;
2900
3721
 
 
3722
 
2901
3723
#ifdef UNIV_DEBUG
2902
3724
                bpage->in_page_hash = FALSE;
2903
3725
                bpage->in_zip_hash = FALSE;
2907
3729
#endif /* UNIV_DEBUG */
2908
3730
 
2909
3731
                ut_d(bpage->in_page_hash = TRUE);
2910
 
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
2911
 
                            buf_page_address_fold(space, offset), bpage);
 
3732
 
 
3733
                if (UNIV_LIKELY_NULL(watch_page)) {
 
3734
                        /* Preserve the reference count. */
 
3735
                        ulint   buf_fix_count = watch_page->buf_fix_count;
 
3736
                        ut_a(buf_fix_count > 0);
 
3737
                        bpage->buf_fix_count += buf_fix_count;
 
3738
                        ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
 
3739
                        buf_pool_watch_remove(buf_pool, fold, watch_page);
 
3740
                }
 
3741
 
 
3742
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
 
3743
                            bpage);
2912
3744
 
2913
3745
                /* The block must be put to the LRU list, to the old blocks */
2914
3746
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
2916
3748
 
2917
3749
                buf_page_set_io_fix(bpage, BUF_IO_READ);
2918
3750
 
2919
 
                mutex_exit(&buf_pool_zip_mutex);
 
3751
                mutex_exit(&buf_pool->zip_mutex);
2920
3752
        }
2921
3753
 
2922
3754
        buf_pool->n_pend_reads++;
2923
3755
func_exit:
2924
 
        buf_pool_mutex_exit();
 
3756
        buf_pool_mutex_exit(buf_pool);
2925
3757
 
2926
3758
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
2927
3759
 
2950
3782
{
2951
3783
        buf_frame_t*    frame;
2952
3784
        buf_block_t*    block;
 
3785
        ulint           fold;
2953
3786
        buf_block_t*    free_block      = NULL;
2954
3787
        ulint           time_ms         = ut_time_ms();
 
3788
        buf_pool_t*     buf_pool        = buf_pool_get(space, offset);
2955
3789
 
2956
3790
        ut_ad(mtr);
 
3791
        ut_ad(mtr->state == MTR_ACTIVE);
2957
3792
        ut_ad(space || !zip_size);
2958
3793
 
2959
 
        free_block = buf_LRU_get_free_block(0);
2960
 
 
2961
 
        buf_pool_mutex_enter();
2962
 
 
2963
 
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2964
 
 
2965
 
        if (block && buf_page_in_file(&block->page)) {
 
3794
        free_block = buf_LRU_get_free_block(buf_pool, 0);
 
3795
 
 
3796
        fold = buf_page_address_fold(space, offset);
 
3797
 
 
3798
        buf_pool_mutex_enter(buf_pool);
 
3799
 
 
3800
        block = (buf_block_t*) buf_page_hash_get_low(
 
3801
                buf_pool, space, offset, fold);
 
3802
 
 
3803
        if (block
 
3804
            && buf_page_in_file(&block->page)
 
3805
            && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2966
3806
#ifdef UNIV_IBUF_COUNT_DEBUG
2967
3807
                ut_a(ibuf_count_get(space, offset) == 0);
2968
3808
#endif
2971
3811
#endif /* UNIV_DEBUG_FILE_ACCESSES */
2972
3812
 
2973
3813
                /* Page can be found in buf_pool */
2974
 
                buf_pool_mutex_exit();
 
3814
                buf_pool_mutex_exit(buf_pool);
2975
3815
 
2976
3816
                buf_block_free(free_block);
2977
3817
 
2992
3832
 
2993
3833
        mutex_enter(&block->mutex);
2994
3834
 
2995
 
        buf_page_init(space, offset, block);
 
3835
        buf_page_init(space, offset, fold, block);
2996
3836
 
2997
3837
        /* The block must be put to the LRU list */
2998
3838
        buf_LRU_add_block(&block->page, FALSE);
3005
3845
                ibool   lru;
3006
3846
 
3007
3847
                /* Prevent race conditions during buf_buddy_alloc(),
3008
 
                which may release and reacquire buf_pool_mutex,
 
3848
                which may release and reacquire buf_pool->mutex,
3009
3849
                by IO-fixing and X-latching the block. */
3010
3850
 
3011
3851
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3013
3853
 
3014
3854
                page_zip_set_size(&block->page.zip, zip_size);
3015
3855
                mutex_exit(&block->mutex);
3016
 
                /* buf_pool_mutex may be released and reacquired by
 
3856
                /* buf_pool->mutex may be released and reacquired by
3017
3857
                buf_buddy_alloc().  Thus, we must release block->mutex
3018
3858
                in order not to break the latching order in
3019
 
                the reacquisition of buf_pool_mutex.  We also must
 
3859
                the reacquisition of buf_pool->mutex.  We also must
3020
3860
                defer this operation until after the block descriptor
3021
3861
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3022
 
                data = buf_buddy_alloc(zip_size, &lru);
 
3862
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
3023
3863
                mutex_enter(&block->mutex);
3024
 
                block->page.zip.data = data;
 
3864
                block->page.zip.data = static_cast<unsigned char *>(data);
3025
3865
 
3026
3866
                /* To maintain the invariant
3027
3867
                block->in_unzip_LRU_list
3037
3877
 
3038
3878
        buf_page_set_accessed(&block->page, time_ms);
3039
3879
 
3040
 
        buf_pool_mutex_exit();
 
3880
        buf_pool_mutex_exit(buf_pool);
3041
3881
 
3042
3882
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3043
3883
 
3049
3889
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3050
3890
 
3051
3891
        /* Flush pages from the end of the LRU list if necessary */
3052
 
        buf_flush_free_margin();
 
3892
        buf_flush_free_margin(buf_pool);
3053
3893
 
3054
3894
        frame = block->frame;
3055
3895
 
3085
3925
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
3086
3926
{
3087
3927
        enum buf_io_fix io_type;
 
3928
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3088
3929
        const ibool     uncompressed = (buf_page_get_state(bpage)
3089
3930
                                        == BUF_BLOCK_FILE_PAGE);
3090
3931
 
3220
4061
                }
3221
4062
        }
3222
4063
 
3223
 
        buf_pool_mutex_enter();
 
4064
        buf_pool_mutex_enter(buf_pool);
3224
4065
        mutex_enter(buf_page_get_mutex(bpage));
3225
4066
 
3226
4067
#ifdef UNIV_IBUF_COUNT_DEBUG
3284
4125
#endif /* UNIV_DEBUG */
3285
4126
 
3286
4127
        mutex_exit(buf_page_get_mutex(bpage));
3287
 
        buf_pool_mutex_exit();
3288
 
}
3289
 
 
3290
 
/*********************************************************************//**
3291
 
Invalidates the file pages in the buffer pool when an archive recovery is
3292
 
completed. All the file pages buffered must be in a replaceable state when
3293
 
this function is called: not latched and not modified. */
3294
 
UNIV_INTERN
 
4128
        buf_pool_mutex_exit(buf_pool);
 
4129
}
 
4130
 
 
4131
/*********************************************************************//**
 
4132
Asserts that all file pages in the buffer are in a replaceable state.
 
4133
@return TRUE */
 
4134
static
 
4135
ibool
 
4136
buf_all_freed_instance(
 
4137
/*===================*/
 
4138
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instancce */
 
4139
{
 
4140
        ulint           i;
 
4141
        buf_chunk_t*    chunk;
 
4142
 
 
4143
        ut_ad(buf_pool);
 
4144
 
 
4145
        buf_pool_mutex_enter(buf_pool);
 
4146
 
 
4147
        chunk = buf_pool->chunks;
 
4148
 
 
4149
        for (i = buf_pool->n_chunks; i--; chunk++) {
 
4150
 
 
4151
                const buf_block_t* block = buf_chunk_not_freed(chunk);
 
4152
 
 
4153
                if (UNIV_LIKELY_NULL(block)) {
 
4154
                        fprintf(stderr,
 
4155
                                "Page %lu %lu still fixed or dirty\n",
 
4156
                                (ulong) block->page.space,
 
4157
                                (ulong) block->page.offset);
 
4158
                        ut_error;
 
4159
                }
 
4160
        }
 
4161
 
 
4162
        buf_pool_mutex_exit(buf_pool);
 
4163
 
 
4164
        return(TRUE);
 
4165
}
 
4166
 
 
4167
/*********************************************************************//**
 
4168
Invalidates file pages in one buffer pool instance */
 
4169
static
3295
4170
void
3296
 
buf_pool_invalidate(void)
3297
 
/*=====================*/
 
4171
buf_pool_invalidate_instance(
 
4172
/*=========================*/
 
4173
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3298
4174
{
3299
4175
        ibool           freed;
3300
 
        enum buf_flush  i;
 
4176
        int     i;
3301
4177
 
3302
 
        buf_pool_mutex_enter();
 
4178
        buf_pool_mutex_enter(buf_pool);
3303
4179
 
3304
4180
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
3305
4181
 
3315
4191
                pool invalidation to proceed we must ensure there is NO
3316
4192
                write activity happening. */
3317
4193
                if (buf_pool->n_flush[i] > 0) {
3318
 
                        buf_pool_mutex_exit();
3319
 
                        buf_flush_wait_batch_end(i);
3320
 
                        buf_pool_mutex_enter();
 
4194
                        buf_pool_mutex_exit(buf_pool);
 
4195
                        buf_flush_wait_batch_end(buf_pool, static_cast<buf_flush>(i));
 
4196
                        buf_pool_mutex_enter(buf_pool);
3321
4197
                }
3322
4198
        }
3323
4199
 
3324
 
        buf_pool_mutex_exit();
 
4200
        buf_pool_mutex_exit(buf_pool);
3325
4201
 
3326
 
        ut_ad(buf_all_freed());
 
4202
        ut_ad(buf_all_freed_instance(buf_pool));
3327
4203
 
3328
4204
        freed = TRUE;
3329
4205
 
3330
4206
        while (freed) {
3331
 
                freed = buf_LRU_search_and_free_block(100);
 
4207
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
3332
4208
        }
3333
4209
 
3334
 
        buf_pool_mutex_enter();
 
4210
        buf_pool_mutex_enter(buf_pool);
3335
4211
 
3336
4212
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
3337
4213
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
3342
4218
        buf_pool->LRU_flush_ended = 0;
3343
4219
 
3344
4220
        memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
3345
 
        buf_refresh_io_stats();
3346
 
 
3347
 
        buf_pool_mutex_exit();
 
4221
        buf_refresh_io_stats(buf_pool);
 
4222
 
 
4223
        buf_pool_mutex_exit(buf_pool);
 
4224
}
 
4225
 
 
4226
/*********************************************************************//**
 
4227
Invalidates the file pages in the buffer pool when an archive recovery is
 
4228
completed. All the file pages buffered must be in a replaceable state when
 
4229
this function is called: not latched and not modified. */
 
4230
UNIV_INTERN
 
4231
void
 
4232
buf_pool_invalidate(void)
 
4233
/*=====================*/
 
4234
{
 
4235
        ulint   i;
 
4236
 
 
4237
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4238
                buf_pool_invalidate_instance(buf_pool_from_array(i));
 
4239
        }
3348
4240
}
3349
4241
 
3350
4242
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3351
4243
/*********************************************************************//**
3352
 
Validates the buffer buf_pool data structure.
 
4244
Validates data in one buffer pool instance
3353
4245
@return TRUE */
3354
 
UNIV_INTERN
 
4246
static
3355
4247
ibool
3356
 
buf_validate(void)
3357
 
/*==============*/
 
4248
buf_pool_validate_instance(
 
4249
/*=======================*/
 
4250
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3358
4251
{
3359
4252
        buf_page_t*     b;
3360
4253
        buf_chunk_t*    chunk;
3369
4262
 
3370
4263
        ut_ad(buf_pool);
3371
4264
 
3372
 
        buf_pool_mutex_enter();
 
4265
        buf_pool_mutex_enter(buf_pool);
3373
4266
 
3374
4267
        chunk = buf_pool->chunks;
3375
4268
 
3394
4287
                                break;
3395
4288
 
3396
4289
                        case BUF_BLOCK_FILE_PAGE:
3397
 
                                ut_a(buf_page_hash_get(buf_block_get_space(
 
4290
                                ut_a(buf_page_hash_get(buf_pool,
 
4291
                                                       buf_block_get_space(
3398
4292
                                                               block),
3399
4293
                                                       buf_block_get_page_no(
3400
4294
                                                               block))
3441
4335
                                }
3442
4336
 
3443
4337
                                n_lru++;
3444
 
 
3445
 
                                if (block->page.oldest_modification > 0) {
3446
 
                                        n_flush++;
3447
 
                                }
3448
 
 
3449
4338
                                break;
3450
4339
 
3451
4340
                        case BUF_BLOCK_NOT_USED:
3463
4352
                }
3464
4353
        }
3465
4354
 
3466
 
        mutex_enter(&buf_pool_zip_mutex);
 
4355
        mutex_enter(&buf_pool->zip_mutex);
3467
4356
 
3468
4357
        /* Check clean compressed-only blocks. */
3469
4358
 
3484
4373
                        ut_error;
3485
4374
                        break;
3486
4375
                }
 
4376
 
 
4377
                /* It is OK to read oldest_modification here because
 
4378
                we have acquired buf_pool->zip_mutex above which acts
 
4379
                as the 'block->mutex' for these bpages. */
3487
4380
                ut_a(!b->oldest_modification);
3488
 
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
 
4381
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3489
4382
 
3490
4383
                n_lru++;
3491
4384
                n_zip++;
3492
4385
        }
3493
4386
 
3494
 
        /* Check dirty compressed-only blocks. */
 
4387
        /* Check dirty blocks. */
3495
4388
 
 
4389
        buf_flush_list_mutex_enter(buf_pool);
3496
4390
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
3497
4391
             b = UT_LIST_GET_NEXT(list, b)) {
3498
4392
                ut_ad(b->in_flush_list);
 
4393
                ut_a(b->oldest_modification);
 
4394
                n_flush++;
3499
4395
 
3500
4396
                switch (buf_page_get_state(b)) {
3501
4397
                case BUF_BLOCK_ZIP_DIRTY:
3502
 
                        ut_a(b->oldest_modification);
3503
4398
                        n_lru++;
3504
 
                        n_flush++;
3505
4399
                        n_zip++;
3506
4400
                        switch (buf_page_get_io_fix(b)) {
3507
4401
                        case BUF_IO_NONE:
3508
4402
                        case BUF_IO_READ:
3509
4403
                                break;
3510
 
 
3511
4404
                        case BUF_IO_WRITE:
3512
4405
                                switch (buf_page_get_flush_type(b)) {
3513
4406
                                case BUF_FLUSH_LRU:
3537
4430
                        ut_error;
3538
4431
                        break;
3539
4432
                }
3540
 
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
 
4433
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
3541
4434
        }
3542
4435
 
3543
 
        mutex_exit(&buf_pool_zip_mutex);
 
4436
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
 
4437
 
 
4438
        buf_flush_list_mutex_exit(buf_pool);
 
4439
 
 
4440
        mutex_exit(&buf_pool->zip_mutex);
3544
4441
 
3545
4442
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
3546
4443
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
3556
4453
                        (ulong) n_free);
3557
4454
                ut_error;
3558
4455
        }
3559
 
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
3560
4456
 
3561
4457
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
3562
4458
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
3563
4459
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
3564
4460
 
3565
 
        buf_pool_mutex_exit();
 
4461
        buf_pool_mutex_exit(buf_pool);
3566
4462
 
3567
4463
        ut_a(buf_LRU_validate());
3568
 
        ut_a(buf_flush_validate());
3569
 
 
3570
 
        return(TRUE);
3571
 
}
 
4464
        ut_a(buf_flush_validate(buf_pool));
 
4465
 
 
4466
        return(TRUE);
 
4467
}
 
4468
 
 
4469
/*********************************************************************//**
 
4470
Validates the buffer buf_pool data structure.
 
4471
@return TRUE */
 
4472
UNIV_INTERN
 
4473
ibool
 
4474
buf_validate(void)
 
4475
/*==============*/
 
4476
{
 
4477
        ulint   i;
 
4478
 
 
4479
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4480
                buf_pool_t*     buf_pool;
 
4481
 
 
4482
                buf_pool = buf_pool_from_array(i);
 
4483
 
 
4484
                buf_pool_validate_instance(buf_pool);
 
4485
        }
 
4486
        return(TRUE);
 
4487
}
 
4488
 
3572
4489
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3573
4490
 
3574
4491
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3575
4492
/*********************************************************************//**
3576
 
Prints info of the buffer buf_pool data structure. */
3577
 
UNIV_INTERN
 
4493
Prints info of the buffer buf_pool data structure for one instance. */
 
4494
static
3578
4495
void
3579
 
buf_print(void)
3580
 
/*===========*/
 
4496
buf_print_instance(
 
4497
/*===============*/
 
4498
        buf_pool_t*     buf_pool)
3581
4499
{
3582
 
        dulint*         index_ids;
 
4500
        index_id_t*     index_ids;
3583
4501
        ulint*          counts;
3584
4502
        ulint           size;
3585
4503
        ulint           i;
3586
4504
        ulint           j;
3587
 
        dulint          id;
 
4505
        index_id_t      id;
3588
4506
        ulint           n_found;
3589
4507
        buf_chunk_t*    chunk;
3590
4508
        dict_index_t*   index;
3593
4511
 
3594
4512
        size = buf_pool->curr_size;
3595
4513
 
3596
 
        index_ids = mem_alloc(sizeof(dulint) * size);
 
4514
        index_ids = mem_alloc(size * sizeof *index_ids);
3597
4515
        counts = mem_alloc(sizeof(ulint) * size);
3598
4516
 
3599
 
        buf_pool_mutex_enter();
 
4517
        buf_pool_mutex_enter(buf_pool);
 
4518
        buf_flush_list_mutex_enter(buf_pool);
3600
4519
 
3601
4520
        fprintf(stderr,
3602
4521
                "buf_pool size %lu\n"
3623
4542
                (ulong) buf_pool->stat.n_pages_created,
3624
4543
                (ulong) buf_pool->stat.n_pages_written);
3625
4544
 
 
4545
        buf_flush_list_mutex_exit(buf_pool);
 
4546
 
3626
4547
        /* Count the number of blocks belonging to each index in the buffer */
3627
4548
 
3628
4549
        n_found = 0;
3645
4566
 
3646
4567
                                while (j < n_found) {
3647
4568
 
3648
 
                                        if (ut_dulint_cmp(index_ids[j],
3649
 
                                                          id) == 0) {
 
4569
                                        if (index_ids[j] == id) {
3650
4570
                                                counts[j]++;
3651
4571
 
3652
4572
                                                break;
3663
4583
                }
3664
4584
        }
3665
4585
 
3666
 
        buf_pool_mutex_exit();
 
4586
        buf_pool_mutex_exit(buf_pool);
3667
4587
 
3668
4588
        for (i = 0; i < n_found; i++) {
3669
4589
                index = dict_index_get_if_in_cache(index_ids[i]);
3670
4590
 
3671
4591
                fprintf(stderr,
3672
 
                        "Block count for index %lu in buffer is about %lu",
3673
 
                        (ulong) ut_dulint_get_low(index_ids[i]),
 
4592
                        "Block count for index %llu in buffer is about %lu",
 
4593
                        (ullint) index_ids[i],
3674
4594
                        (ulong) counts[i]);
3675
4595
 
3676
4596
                if (index) {
3684
4604
        mem_free(index_ids);
3685
4605
        mem_free(counts);
3686
4606
 
3687
 
        ut_a(buf_validate());
 
4607
        ut_a(buf_pool_validate_instance(buf_pool));
 
4608
}
 
4609
 
 
4610
/*********************************************************************//**
 
4611
Prints info of the buffer buf_pool data structure. */
 
4612
UNIV_INTERN
 
4613
void
 
4614
buf_print(void)
 
4615
/*===========*/
 
4616
{
 
4617
        ulint   i;
 
4618
 
 
4619
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4620
                buf_pool_t*     buf_pool;
 
4621
 
 
4622
                buf_pool = buf_pool_from_array(i);
 
4623
                buf_print_instance(buf_pool);
 
4624
        }
3688
4625
}
3689
4626
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
3690
4627
 
3694
4631
@return number of latched pages */
3695
4632
UNIV_INTERN
3696
4633
ulint
3697
 
buf_get_latched_pages_number(void)
3698
 
/*==============================*/
 
4634
buf_get_latched_pages_number_instance(
 
4635
/*==================================*/
 
4636
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3699
4637
{
3700
 
        buf_chunk_t*    chunk;
3701
4638
        buf_page_t*     b;
3702
4639
        ulint           i;
 
4640
        buf_chunk_t*    chunk;
3703
4641
        ulint           fixed_pages_number = 0;
3704
4642
 
3705
 
        buf_pool_mutex_enter();
 
4643
        buf_pool_mutex_enter(buf_pool);
3706
4644
 
3707
4645
        chunk = buf_pool->chunks;
3708
4646
 
3731
4669
                }
3732
4670
        }
3733
4671
 
3734
 
        mutex_enter(&buf_pool_zip_mutex);
 
4672
        mutex_enter(&buf_pool->zip_mutex);
3735
4673
 
3736
4674
        /* Traverse the lists of clean and dirty compressed-only blocks. */
3737
4675
 
3746
4684
                }
3747
4685
        }
3748
4686
 
 
4687
        buf_flush_list_mutex_enter(buf_pool);
3749
4688
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
3750
4689
             b = UT_LIST_GET_NEXT(list, b)) {
3751
4690
                ut_ad(b->in_flush_list);
3771
4710
                }
3772
4711
        }
3773
4712
 
3774
 
        mutex_exit(&buf_pool_zip_mutex);
3775
 
        buf_pool_mutex_exit();
 
4713
        buf_flush_list_mutex_exit(buf_pool);
 
4714
        mutex_exit(&buf_pool->zip_mutex);
 
4715
        buf_pool_mutex_exit(buf_pool);
3776
4716
 
3777
4717
        return(fixed_pages_number);
3778
4718
}
 
4719
 
 
4720
/*********************************************************************//**
 
4721
Returns the number of latched pages in all the buffer pools.
 
4722
@return number of latched pages */
 
4723
UNIV_INTERN
 
4724
ulint
 
4725
buf_get_latched_pages_number(void)
 
4726
/*==============================*/
 
4727
{
 
4728
        ulint   i;
 
4729
        ulint   total_latched_pages = 0;
 
4730
 
 
4731
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4732
                buf_pool_t*     buf_pool;
 
4733
 
 
4734
                buf_pool = buf_pool_from_array(i);
 
4735
 
 
4736
                total_latched_pages += buf_get_latched_pages_number_instance(
 
4737
                        buf_pool);
 
4738
        }
 
4739
 
 
4740
        return(total_latched_pages);
 
4741
}
 
4742
 
3779
4743
#endif /* UNIV_DEBUG */
3780
4744
 
3781
4745
/*********************************************************************//**
3786
4750
buf_get_n_pending_ios(void)
3787
4751
/*=======================*/
3788
4752
{
3789
 
        return(buf_pool->n_pend_reads
3790
 
               + buf_pool->n_flush[BUF_FLUSH_LRU]
3791
 
               + buf_pool->n_flush[BUF_FLUSH_LIST]
3792
 
               + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
 
4753
        ulint   i;
 
4754
        ulint   pend_ios = 0;
 
4755
 
 
4756
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4757
                buf_pool_t*     buf_pool;
 
4758
 
 
4759
                buf_pool = buf_pool_from_array(i);
 
4760
 
 
4761
                pend_ios +=
 
4762
                        buf_pool->n_pend_reads
 
4763
                        + buf_pool->n_flush[BUF_FLUSH_LRU]
 
4764
                        + buf_pool->n_flush[BUF_FLUSH_LIST]
 
4765
                        + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
 
4766
        }
 
4767
 
 
4768
        return(pend_ios);
3793
4769
}
3794
4770
 
3795
4771
/*********************************************************************//**
3801
4777
buf_get_modified_ratio_pct(void)
3802
4778
/*============================*/
3803
4779
{
3804
 
        ulint   ratio;
3805
 
 
3806
 
        buf_pool_mutex_enter();
3807
 
 
3808
 
        ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
3809
 
                / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
3810
 
                   + UT_LIST_GET_LEN(buf_pool->free));
3811
 
 
 
4780
        ulint           ratio;
 
4781
        ulint           lru_len = 0;
 
4782
        ulint           free_len = 0;
 
4783
        ulint           flush_list_len = 0;
 
4784
 
 
4785
        buf_get_total_list_len(&lru_len, &free_len, &flush_list_len);
 
4786
 
 
4787
        ratio = (100 * flush_list_len) / (1 + lru_len + free_len);
 
4788
  
3812
4789
        /* 1 + is there to avoid division by zero */
3813
4790
 
3814
 
        buf_pool_mutex_exit();
3815
 
 
3816
4791
        return(ratio);
3817
4792
}
3818
4793
 
3819
4794
/*********************************************************************//**
3820
4795
Prints info of the buffer i/o. */
3821
 
UNIV_INTERN
 
4796
static
3822
4797
void
3823
 
buf_print_io(
3824
 
/*=========*/
3825
 
        FILE*   file)   /*!< in/out: buffer where to print */
 
4798
buf_print_io_instance(
 
4799
/*==================*/
 
4800
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
 
4801
        FILE*           file)           /*!< in/out: buffer where to print */
3826
4802
{
3827
4803
        time_t  current_time;
3828
4804
        double  time_elapsed;
3830
4806
 
3831
4807
        ut_ad(buf_pool);
3832
4808
 
3833
 
        buf_pool_mutex_enter();
 
4809
        buf_pool_mutex_enter(buf_pool);
 
4810
        buf_flush_list_mutex_enter(buf_pool);
3834
4811
 
3835
4812
        fprintf(file,
3836
4813
                "Buffer pool size   %lu\n"
3852
4829
                + buf_pool->init_flush[BUF_FLUSH_LIST],
3853
4830
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
3854
4831
 
 
4832
        buf_flush_list_mutex_exit(buf_pool);
 
4833
 
3855
4834
        current_time = time(NULL);
3856
4835
        time_elapsed = 0.001 + difftime(current_time,
3857
4836
                                        buf_pool->last_printout_time);
3882
4861
                 - buf_pool->old_stat.n_pages_written)
3883
4862
                / time_elapsed);
3884
4863
 
3885
 
        n_gets_diff = buf_pool->stat.n_page_gets - buf_pool->old_stat.n_page_gets;
 
4864
        n_gets_diff = buf_pool->stat.n_page_gets
 
4865
                    - buf_pool->old_stat.n_page_gets;
3886
4866
 
3887
4867
        if (n_gets_diff) {
3888
4868
                fprintf(file,
3921
4901
        fprintf(file,
3922
4902
                "LRU len: %lu, unzip_LRU len: %lu\n"
3923
4903
                "I/O sum[%lu]:cur[%lu], unzip sum[%lu]:cur[%lu]\n",
3924
 
                UT_LIST_GET_LEN(buf_pool->LRU),
3925
 
                UT_LIST_GET_LEN(buf_pool->unzip_LRU),
 
4904
                static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->LRU)),
 
4905
                static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->unzip_LRU)),
3926
4906
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
3927
4907
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
3928
4908
 
3929
 
        buf_refresh_io_stats();
3930
 
        buf_pool_mutex_exit();
 
4909
        buf_refresh_io_stats(buf_pool);
 
4910
        buf_pool_mutex_exit(buf_pool);
 
4911
}
 
4912
 
 
4913
/*********************************************************************//**
 
4914
Prints info of the buffer i/o. */
 
4915
UNIV_INTERN
 
4916
void
 
4917
buf_print_io(
 
4918
/*=========*/
 
4919
        FILE*   file)   /*!< in/out: buffer where to print */
 
4920
{
 
4921
        ulint   i;
 
4922
 
 
4923
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4924
                buf_pool_t*     buf_pool;
 
4925
 
 
4926
                buf_pool = buf_pool_from_array(i);
 
4927
                buf_print_io_instance(buf_pool, file);
 
4928
        }
3931
4929
}
3932
4930
 
3933
4931
/**********************************************************************//**
3934
4932
Refreshes the statistics used to print per-second averages. */
3935
4933
UNIV_INTERN
3936
4934
void
3937
 
buf_refresh_io_stats(void)
3938
 
/*======================*/
 
4935
buf_refresh_io_stats(
 
4936
/*=================*/
 
4937
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
3939
4938
{
3940
 
        buf_pool->last_printout_time = time(NULL);
 
4939
        buf_pool->last_printout_time = ut_time();
3941
4940
        buf_pool->old_stat = buf_pool->stat;
3942
4941
}
3943
4942
 
3944
 
/*********************************************************************//**
3945
 
Asserts that all file pages in the buffer are in a replaceable state.
3946
 
@return TRUE */
 
4943
/**********************************************************************//**
 
4944
Refreshes the statistics used to print per-second averages. */
 
4945
UNIV_INTERN
 
4946
void
 
4947
buf_refresh_io_stats_all(void)
 
4948
/*==========================*/
 
4949
{
 
4950
        ulint           i;
 
4951
 
 
4952
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4953
                buf_pool_t*     buf_pool;
 
4954
 
 
4955
                buf_pool = buf_pool_from_array(i);
 
4956
 
 
4957
                buf_refresh_io_stats(buf_pool);
 
4958
        }
 
4959
}
 
4960
 
 
4961
/**********************************************************************//**
 
4962
Check if all pages in all buffer pools are in a replacable state.
 
4963
@return FALSE if not */
3947
4964
UNIV_INTERN
3948
4965
ibool
3949
4966
buf_all_freed(void)
3950
4967
/*===============*/
3951
4968
{
3952
 
        buf_chunk_t*    chunk;
3953
 
        ulint           i;
3954
 
 
3955
 
        ut_ad(buf_pool);
3956
 
 
3957
 
        buf_pool_mutex_enter();
3958
 
 
3959
 
        chunk = buf_pool->chunks;
3960
 
 
3961
 
        for (i = buf_pool->n_chunks; i--; chunk++) {
3962
 
 
3963
 
                const buf_block_t* block = buf_chunk_not_freed(chunk);
3964
 
 
3965
 
                if (UNIV_LIKELY_NULL(block)) {
3966
 
                        fprintf(stderr,
3967
 
                                "Page %lu %lu still fixed or dirty\n",
3968
 
                                (ulong) block->page.space,
3969
 
                                (ulong) block->page.offset);
3970
 
                        ut_error;
 
4969
        ulint   i;
 
4970
 
 
4971
        for (i = 0; i < srv_buf_pool_instances; i++) {
 
4972
                buf_pool_t*     buf_pool;
 
4973
 
 
4974
                buf_pool = buf_pool_from_array(i);
 
4975
 
 
4976
                if (!buf_all_freed_instance(buf_pool)) {
 
4977
                        return(FALSE);
3971
4978
                }
3972
 
        }
3973
 
 
3974
 
        buf_pool_mutex_exit();
 
4979
        }
3975
4980
 
3976
4981
        return(TRUE);
3977
4982
}
3978
 
 
 
4983
  
3979
4984
/*********************************************************************//**
3980
4985
Checks that there currently are no pending i/o-operations for the buffer
3981
4986
pool.
3985
4990
buf_pool_check_no_pending_io(void)
3986
4991
/*==============================*/
3987
4992
{
3988
 
        ibool   ret;
3989
 
 
3990
 
        buf_pool_mutex_enter();
3991
 
 
3992
 
        if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
3993
 
            + buf_pool->n_flush[BUF_FLUSH_LIST]
3994
 
            + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
3995
 
                ret = FALSE;
3996
 
        } else {
3997
 
                ret = TRUE;
 
4993
        ulint           i;
 
4994
        ibool           ret = TRUE;
 
4995
 
 
4996
        buf_pool_mutex_enter_all();
 
4997
 
 
4998
        for (i = 0; i < srv_buf_pool_instances && ret; i++) {
 
4999
                const buf_pool_t*       buf_pool;
 
5000
 
 
5001
                buf_pool = buf_pool_from_array(i);
 
5002
 
 
5003
                if (buf_pool->n_pend_reads
 
5004
                    + buf_pool->n_flush[BUF_FLUSH_LRU]
 
5005
                    + buf_pool->n_flush[BUF_FLUSH_LIST]
 
5006
                    + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
 
5007
 
 
5008
                        ret = FALSE;
 
5009
                }
3998
5010
        }
3999
5011
 
4000
 
        buf_pool_mutex_exit();
 
5012
        buf_pool_mutex_exit_all();
4001
5013
 
4002
5014
        return(ret);
4003
5015
}
4004
5016
 
 
5017
#if 0
 
5018
Code currently not used
4005
5019
/*********************************************************************//**
4006
5020
Gets the current length of the free list of buffer blocks.
4007
5021
@return length of the free list */
4012
5026
{
4013
5027
        ulint   len;
4014
5028
 
4015
 
        buf_pool_mutex_enter();
 
5029
        buf_pool_mutex_enter(buf_pool);
4016
5030
 
4017
5031
        len = UT_LIST_GET_LEN(buf_pool->free);
4018
5032
 
4019
 
        buf_pool_mutex_exit();
 
5033
        buf_pool_mutex_exit(buf_pool);
4020
5034
 
4021
5035
        return(len);
4022
5036
}
 
5037
#endif
 
5038
 
4023
5039
#else /* !UNIV_HOTBACKUP */
4024
5040
/********************************************************************//**
4025
5041
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */