~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-08-03 18:21:58 UTC
  • mto: (1680.2.6 build)
  • mto: This revision was merged to the branch mainline in revision 1683.
  • Revision ID: mordred@inaugust.com-20100803182158-nkmgnlohodud4290
Made existence of intltool and gettext optional.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
 
3
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
 
4
Copyright (c) 2008, Google Inc.
5
5
 
6
6
Portions of this file contain modifications contributed and copyrighted by
7
7
Google, Inc. Those modifications are gratefully acknowledged and are described
18
18
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
19
 
20
20
You should have received a copy of the GNU General Public License along with
21
 
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
 
St, Fifth Floor, Boston, MA 02110-1301 USA
 
21
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
22
Place, Suite 330, Boston, MA 02111-1307 USA
23
23
 
24
24
*****************************************************************************/
25
25
 
52
52
#include "log0recv.h"
53
53
#include "page0zip.h"
54
54
 
55
 
#include <drizzled/errmsg_print.h>
56
 
 
57
55
/*
58
56
                IMPLEMENTATION OF THE BUFFER POOL
59
57
                =================================
86
84
The buffer buf_pool contains a single mutex which protects all the
87
85
control data structures of the buf_pool. The content of a buffer frame is
88
86
protected by a separate read-write lock in its control block, though.
89
 
These locks can be locked and unlocked without owning the buf_pool->mutex.
 
87
These locks can be locked and unlocked without owning the buf_pool mutex.
90
88
The OS events in the buf_pool struct can be waited for without owning the
91
 
buf_pool->mutex.
 
89
buf_pool mutex.
92
90
 
93
 
The buf_pool->mutex is a hot-spot in main memory, causing a lot of
 
91
The buf_pool mutex is a hot-spot in main memory, causing a lot of
94
92
memory bus traffic on multiprocessor systems when processors
95
93
alternately access the mutex. On our Pentium, the mutex is accessed
96
94
maybe every 10 microseconds. We gave up the solution to have mutexes
97
95
for each control block, for instance, because it seemed to be
98
96
complicated.
99
97
 
100
 
A solution to reduce mutex contention of the buf_pool->mutex is to
 
98
A solution to reduce mutex contention of the buf_pool mutex is to
101
99
create a separate mutex for the page hash table. On Pentium,
102
100
accessing the hash table takes 2 microseconds, about half
103
 
of the total buf_pool->mutex hold time.
 
101
of the total buf_pool mutex hold time.
104
102
 
105
103
                Control blocks
106
104
                --------------
155
153
which we can use when we want to artificially age a page in the
156
154
buf_pool. This is used if we know that some page is not needed
157
155
again for some time: we insert the block right after the pointer,
158
 
causing it to be replaced sooner than would normally be the case.
 
156
causing it to be replaced sooner than would noramlly be the case.
159
157
Currently this aging mechanism is used for read-ahead mechanism
160
158
of pages, and it can also be used when there is a scan of a full
161
159
table which cannot fit in the memory. Putting the pages near the
162
 
end of the LRU list, we make sure that most of the buf_pool stays
163
 
in the main memory, undisturbed.
 
160
of the LRU list, we make sure that most of the buf_pool stays in the
 
161
main memory, undisturbed.
164
162
 
165
163
The unzip_LRU list contains a subset of the common LRU list.  The
166
164
blocks on the unzip_LRU list hold a compressed file page and the
174
172
holding file pages that have been modified in the memory
175
173
but not written to disk yet. The block with the oldest modification
176
174
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.
178
175
 
179
176
The chain of unmodified compressed blocks (buf_pool->zip_clean)
180
177
contains the control blocks (buf_page_t) of those compressed pages
245
242
#ifndef UNIV_HOTBACKUP
246
243
/** Value in microseconds */
247
244
static const int WAIT_FOR_READ  = 5000;
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;
 
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;
253
255
 
254
256
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
255
257
static ulint    buf_dbg_counter = 0; /*!< This is used to insert validation
256
 
                                        operations in execution in the
 
258
                                        operations in excution in the
257
259
                                        debug version */
 
260
/** Flag to forbid the release of the buffer pool mutex.
 
261
Protected by buf_pool_mutex. */
 
262
UNIV_INTERN ulint               buf_pool_mutex_exit_forbidden = 0;
258
263
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
259
264
#ifdef UNIV_DEBUG
260
265
/** If this is set TRUE, the program prints info whenever
262
267
UNIV_INTERN ibool               buf_debug_prints = FALSE;
263
268
#endif /* UNIV_DEBUG */
264
269
 
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
 
 
299
270
/** A chunk of buffers.  The buffer pool is allocated in chunks. */
300
271
struct buf_chunk_struct{
301
272
        ulint           mem_size;       /*!< allocated size of the chunk */
307
278
#endif /* !UNIV_HOTBACKUP */
308
279
 
309
280
/********************************************************************//**
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
 
/********************************************************************//**
444
281
Calculates a page checksum which is stored to the page when it is written
445
282
to a file. Note that we must be careful to calculate the same value on
446
283
32-bit and 64-bit architectures.
524
361
                ib_uint64_t     current_lsn;
525
362
 
526
363
                if (log_peek_lsn(&current_lsn)
527
 
                    && UNIV_UNLIKELY
528
 
                    (current_lsn
529
 
                     < mach_read_from_8(read_buf + FIL_PAGE_LSN))) {
 
364
                    && current_lsn < mach_read_ull(read_buf + FIL_PAGE_LSN)) {
530
365
                        ut_print_timestamp(stderr);
531
366
 
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);
 
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);
541
382
                }
542
383
        }
543
384
#endif
733
574
#endif /* !UNIV_HOTBACKUP */
734
575
 
735
576
        switch (fil_page_get_type(read_buf)) {
736
 
                index_id_t      index_id;
737
577
        case FIL_PAGE_INDEX:
738
 
                index_id = btr_page_get_index_id(read_buf);
739
578
                fprintf(stderr,
740
579
                        "InnoDB: Page may be an index page where"
741
 
                        " index id is %llu\n",
742
 
                        (ullint) index_id);
 
580
                        " index id is %lu %lu\n",
 
581
                        (ulong) ut_dulint_get_high(
 
582
                                btr_page_get_index_id(read_buf)),
 
583
                        (ulong) ut_dulint_get_low(
 
584
                                btr_page_get_index_id(read_buf)));
743
585
#ifndef UNIV_HOTBACKUP
744
 
                index = dict_index_find_on_id_low(index_id);
 
586
                index = dict_index_find_on_id_low(
 
587
                        btr_page_get_index_id(read_buf));
745
588
                if (index) {
746
589
                        fputs("InnoDB: (", stderr);
747
590
                        dict_index_name_print(stderr, NULL, index);
793
636
}
794
637
 
795
638
#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
 
 
843
639
/********************************************************************//**
844
640
Initializes a buffer control block when the buf_pool is created. */
845
641
static
846
642
void
847
643
buf_block_init(
848
644
/*===========*/
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 */
 
645
        buf_block_t*    block,  /*!< in: pointer to control block */
 
646
        byte*           frame)  /*!< in: pointer to buffer frame */
852
647
{
853
648
        UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
854
649
 
855
650
        block->frame = frame;
856
651
 
857
 
        block->page.buf_pool_index = buf_pool_index(buf_pool);
858
652
        block->page.state = BUF_BLOCK_NOT_USED;
859
653
        block->page.buf_fix_count = 0;
860
654
        block->page.io_fix = BUF_IO_NONE;
868
662
        block->check_index_page_at_flush = FALSE;
869
663
        block->index = NULL;
870
664
 
871
 
        block->is_hashed = FALSE;
872
 
 
873
665
#ifdef UNIV_DEBUG
874
666
        block->page.in_page_hash = FALSE;
875
667
        block->page.in_zip_hash = FALSE;
883
675
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
884
676
        page_zip_des_init(&block->page.zip);
885
677
 
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
 
 
 
678
        mutex_create(&block->mutex, SYNC_BUF_BLOCK);
 
679
 
 
680
        rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
900
681
        ut_ad(rw_lock_validate(&(block->lock)));
901
682
 
902
683
#ifdef UNIV_SYNC_DEBUG
903
 
        rw_lock_create(buf_block_debug_latch_key,
904
 
                       &block->debug_latch, SYNC_NO_ORDER_CHECK);
 
684
        rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
905
685
#endif /* UNIV_SYNC_DEBUG */
906
686
}
907
687
 
912
692
buf_chunk_t*
913
693
buf_chunk_init(
914
694
/*===========*/
915
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
916
695
        buf_chunk_t*    chunk,          /*!< out: chunk of buffers */
917
696
        ulint           mem_size)       /*!< in: requested size in bytes */
918
697
{
937
716
 
938
717
        /* Allocate the block descriptors from
939
718
        the start of the memory block. */
940
 
        chunk->blocks = static_cast<buf_block_struct *>(chunk->mem);
 
719
        chunk->blocks = chunk->mem;
941
720
 
942
721
        /* Align a pointer to the first frame.  Note that when
943
722
        os_large_page_size is smaller than UNIV_PAGE_SIZE,
944
723
        we may allocate one fewer block than requested.  When
945
724
        it is bigger, we may allocate more blocks than requested. */
946
725
 
947
 
        frame = static_cast<unsigned char *>(ut_align(chunk->mem, UNIV_PAGE_SIZE));
 
726
        frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
948
727
        chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
949
728
                - (frame != chunk->mem);
950
729
 
968
747
 
969
748
        for (i = chunk->size; i--; ) {
970
749
 
971
 
                buf_block_init(buf_pool, block, frame);
 
750
                buf_block_init(block, frame);
972
751
 
973
 
#ifdef HAVE_VALGRIND
 
752
#ifdef HAVE_purify
974
753
                /* Wipe contents of frame to eliminate a Purify warning */
975
754
                memset(block->frame, '\0', UNIV_PAGE_SIZE);
976
755
#endif
977
756
                /* Add the block to the free list */
978
757
                UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
979
 
 
980
758
                ut_d(block->page.in_free_list = TRUE);
981
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
982
759
 
983
760
                block++;
984
761
                frame += UNIV_PAGE_SIZE;
985
762
        }
986
763
 
987
 
#ifdef PFS_GROUP_BUFFER_SYNC
988
 
        pfs_register_buffer_block(chunk);
989
 
#endif
990
764
        return(chunk);
991
765
}
992
766
 
1005
779
        buf_block_t*    block;
1006
780
        ulint           i;
1007
781
 
 
782
        ut_ad(buf_pool);
 
783
        ut_ad(buf_pool_mutex_own());
 
784
 
1008
785
        block = chunk->blocks;
1009
786
 
1010
787
        for (i = chunk->size; i--; block++) {
1025
802
buf_block_t*
1026
803
buf_pool_contains_zip(
1027
804
/*==================*/
1028
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1029
 
        const void*     data)           /*!< in: pointer to compressed page */
 
805
        const void*     data)   /*!< in: pointer to compressed page */
1030
806
{
1031
807
        ulint           n;
1032
808
        buf_chunk_t*    chunk = buf_pool->chunks;
1033
809
 
1034
 
        ut_ad(buf_pool);
1035
 
        ut_ad(buf_pool_mutex_own(buf_pool));
1036
810
        for (n = buf_pool->n_chunks; n--; chunk++) {
1037
 
 
1038
811
                buf_block_t* block = buf_chunk_contains_zip(chunk, data);
1039
812
 
1040
813
                if (block) {
1058
831
        buf_block_t*    block;
1059
832
        ulint           i;
1060
833
 
 
834
        ut_ad(buf_pool);
 
835
        ut_ad(buf_pool_mutex_own());
 
836
 
1061
837
        block = chunk->blocks;
1062
838
 
1063
839
        for (i = chunk->size; i--; block++) {
1064
 
                ibool   ready;
1065
 
 
1066
 
                switch (buf_block_get_state(block)) {
1067
 
                case BUF_BLOCK_ZIP_FREE:
1068
 
                case BUF_BLOCK_ZIP_PAGE:
1069
 
                case BUF_BLOCK_ZIP_DIRTY:
1070
 
                        /* The uncompressed buffer pool should never
1071
 
                        contain compressed block descriptors. */
1072
 
                        ut_error;
1073
 
                        break;
1074
 
                case BUF_BLOCK_NOT_USED:
1075
 
                case BUF_BLOCK_READY_FOR_USE:
1076
 
                case BUF_BLOCK_MEMORY:
1077
 
                case BUF_BLOCK_REMOVE_HASH:
1078
 
                        /* Skip blocks that are not being used for
1079
 
                        file pages. */
1080
 
                        break;
1081
 
                case BUF_BLOCK_FILE_PAGE:
1082
 
                        mutex_enter(&block->mutex);
1083
 
                        ready = buf_flush_ready_for_replace(&block->page);
 
840
                mutex_enter(&block->mutex);
 
841
 
 
842
                if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
 
843
                    && !buf_flush_ready_for_replace(&block->page)) {
 
844
 
1084
845
                        mutex_exit(&block->mutex);
1085
 
 
1086
 
                        if (!ready) {
1087
 
 
1088
 
                                return(block);
1089
 
                        }
1090
 
 
1091
 
                        break;
 
846
                        return(block);
1092
847
                }
 
848
 
 
849
                mutex_exit(&block->mutex);
1093
850
        }
1094
851
 
1095
852
        return(NULL);
1107
864
        const buf_block_t*      block;
1108
865
        ulint                   i;
1109
866
 
 
867
        ut_ad(buf_pool);
 
868
        ut_ad(buf_pool_mutex_own());
 
869
 
1110
870
        block = chunk->blocks;
1111
871
 
1112
872
        for (i = chunk->size; i--; block++) {
1126
886
void
1127
887
buf_chunk_free(
1128
888
/*===========*/
1129
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1130
889
        buf_chunk_t*    chunk)          /*!< out: chunk of buffers */
1131
890
{
1132
891
        buf_block_t*            block;
1133
892
        const buf_block_t*      block_end;
1134
893
 
1135
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
894
        ut_ad(buf_pool_mutex_own());
1136
895
 
1137
896
        block_end = chunk->blocks + chunk->size;
1138
897
 
1160
919
}
1161
920
 
1162
921
/********************************************************************//**
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
 
{
 
922
Creates the buffer pool.
 
923
@return own: buf_pool object, NULL if not enough memory or error */
 
924
UNIV_INTERN
 
925
buf_pool_t*
 
926
buf_pool_init(void)
 
927
/*===============*/
 
928
{
 
929
        buf_chunk_t*    chunk;
1198
930
        ulint           i;
1199
 
        buf_chunk_t*    chunk;
 
931
 
 
932
        buf_pool = mem_zalloc(sizeof(buf_pool_t));
1200
933
 
1201
934
        /* 1. Initialize general fields
1202
935
        ------------------------------- */
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();
 
936
        mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
 
937
        mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
 
938
 
 
939
        buf_pool_mutex_enter();
 
940
 
 
941
        buf_pool->n_chunks = 1;
 
942
        buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
 
943
 
 
944
        UT_LIST_INIT(buf_pool->free);
 
945
 
 
946
        if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
 
947
                mem_free(chunk);
 
948
                mem_free(buf_pool);
 
949
                buf_pool = NULL;
 
950
                return(NULL);
1235
951
        }
 
952
 
 
953
        srv_buf_pool_old_size = srv_buf_pool_size;
 
954
        buf_pool->curr_size = chunk->size;
 
955
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
956
 
 
957
        buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
 
958
        buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
 
959
 
 
960
        buf_pool->last_printout_time = time(NULL);
 
961
 
1236
962
        /* 2. Initialize flushing fields
1237
963
        -------------------------------- */
1238
964
 
1239
 
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1240
 
                     SYNC_BUF_FLUSH_LIST);
1241
 
 
1242
965
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
1243
966
                buf_pool->no_flush[i] = os_event_create(NULL);
1244
967
        }
1245
968
 
 
969
        buf_pool->ulint_clock = 1;
 
970
 
1246
971
        /* 3. Initialize LRU fields
1247
972
        --------------------------- */
1248
 
 
1249
 
        /* All fields are initialized by mem_zalloc(). */
1250
 
 
1251
 
        buf_pool_mutex_exit(buf_pool);
1252
 
 
1253
 
        return(DB_SUCCESS);
 
973
        /* All fields are initialized by mem_zalloc(). */
 
974
 
 
975
        buf_pool_mutex_exit();
 
976
 
 
977
        btr_search_sys_create(buf_pool->curr_size
 
978
                              * UNIV_PAGE_SIZE / sizeof(void*) / 64);
 
979
 
 
980
        /* 4. Initialize the buddy allocator fields */
 
981
        /* All fields are initialized by mem_zalloc(). */
 
982
 
 
983
        return(buf_pool);
1254
984
}
1255
985
 
1256
986
/********************************************************************//**
1257
 
free one buffer pool instance */
1258
 
static
 
987
Frees the buffer pool at shutdown.  This must not be invoked before
 
988
freeing all mutexes. */
 
989
UNIV_INTERN
1259
990
void
1260
 
buf_pool_free_instance(
1261
 
/*===================*/
1262
 
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
1263
 
                                        to free */
 
991
buf_pool_free(void)
 
992
/*===============*/
1264
993
{
1265
994
        buf_chunk_t*    chunk;
1266
995
        buf_chunk_t*    chunks;
1274
1003
                os_mem_free_large(chunk->mem, chunk->mem_size);
1275
1004
        }
1276
1005
 
1277
 
        mem_free(buf_pool->chunks);
1278
 
        hash_table_free(buf_pool->page_hash);
1279
 
        hash_table_free(buf_pool->zip_hash);
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
 
 
 
1006
        buf_pool->n_chunks = 0;
 
1007
}
 
1008
 
1416
1009
/********************************************************************//**
1417
1010
Drops the adaptive hash index.  To prevent a livelock, this function
1418
1011
is only to be called while holding btr_search_latch and while
1430
1023
        ut_ad(!btr_search_enabled);
1431
1024
 
1432
1025
        do {
1433
 
                ulint   i;
 
1026
                buf_chunk_t*    chunks  = buf_pool->chunks;
 
1027
                buf_chunk_t*    chunk   = chunks + buf_pool->n_chunks;
1434
1028
 
1435
1029
                released_search_latch = FALSE;
1436
1030
 
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);
 
1031
                while (--chunk >= chunks) {
 
1032
                        buf_block_t*    block   = chunk->blocks;
 
1033
                        ulint           i       = chunk->size;
 
1034
 
 
1035
                        for (; i--; block++) {
 
1036
                                /* block->is_hashed cannot be modified
 
1037
                                when we have an x-latch on btr_search_latch;
 
1038
                                see the comment in buf0buf.h */
 
1039
 
 
1040
                                if (!block->is_hashed) {
 
1041
                                        continue;
 
1042
                                }
 
1043
 
 
1044
                                /* To follow the latching order, we
 
1045
                                have to release btr_search_latch
 
1046
                                before acquiring block->latch. */
 
1047
                                rw_lock_x_unlock(&btr_search_latch);
 
1048
                                /* When we release the search latch,
 
1049
                                we must rescan all blocks, because
 
1050
                                some may become hashed again. */
 
1051
                                released_search_latch = TRUE;
 
1052
 
 
1053
                                rw_lock_x_lock(&block->lock);
 
1054
 
 
1055
                                /* This should be guaranteed by the
 
1056
                                callers, which will be holding
 
1057
                                btr_search_enabled_mutex. */
 
1058
                                ut_ad(!btr_search_enabled);
 
1059
 
 
1060
                                /* Because we did not buffer-fix the
 
1061
                                block by calling buf_block_get_gen(),
 
1062
                                it is possible that the block has been
 
1063
                                allocated for some other use after
 
1064
                                btr_search_latch was released above.
 
1065
                                We do not care which file page the
 
1066
                                block is mapped to.  All we want to do
 
1067
                                is to drop any hash entries referring
 
1068
                                to the page. */
 
1069
 
 
1070
                                /* It is possible that
 
1071
                                block->page.state != BUF_FILE_PAGE.
 
1072
                                Even that does not matter, because
 
1073
                                btr_search_drop_page_hash_index() will
 
1074
                                check block->is_hashed before doing
 
1075
                                anything.  block->is_hashed can only
 
1076
                                be set on uncompressed file pages. */
 
1077
 
 
1078
                                btr_search_drop_page_hash_index(block);
 
1079
 
 
1080
                                rw_lock_x_unlock(&block->lock);
 
1081
 
 
1082
                                rw_lock_x_lock(&btr_search_latch);
 
1083
 
 
1084
                                ut_ad(!btr_search_enabled);
 
1085
                        }
1444
1086
                }
1445
 
 
1446
1087
        } while (released_search_latch);
1447
1088
}
1448
1089
 
1461
1102
{
1462
1103
        buf_page_t*     b;
1463
1104
        ulint           fold;
1464
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1465
1105
 
1466
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1106
        ut_ad(buf_pool_mutex_own());
1467
1107
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1468
1108
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1469
1109
        ut_a(bpage->buf_fix_count == 0);
1470
1110
        ut_ad(bpage->in_LRU_list);
1471
1111
        ut_ad(!bpage->in_zip_hash);
1472
1112
        ut_ad(bpage->in_page_hash);
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));
 
1113
        ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
1476
1114
#ifdef UNIV_DEBUG
1477
1115
        switch (buf_page_get_state(bpage)) {
1478
1116
        case BUF_BLOCK_ZIP_FREE:
1508
1146
#ifdef UNIV_LRU_DEBUG
1509
1147
                /* buf_pool->LRU_old must be the first item in the LRU list
1510
1148
                whose "old" flag is set. */
1511
 
                ut_a(buf_pool->LRU_old->old);
1512
1149
                ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
1513
1150
                     || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
1514
1151
                ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
1515
1152
                     || UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)->old);
1516
 
        } else {
1517
 
                /* Check that the "old" flag is consistent in
1518
 
                the block and its neighbours. */
1519
 
                buf_page_set_old(dpage, buf_page_is_old(dpage));
1520
1153
#endif /* UNIV_LRU_DEBUG */
1521
1154
        }
1522
1155
 
1528
1161
 
1529
1162
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
1530
1163
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
 
1164
 
 
1165
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
1531
1166
}
1532
1167
 
1533
1168
/********************************************************************//**
1534
 
Shrinks a buffer pool instance. */
 
1169
Shrinks the buffer pool. */
1535
1170
static
1536
1171
void
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 */
 
1172
buf_pool_shrink(
 
1173
/*============*/
 
1174
        ulint   chunk_size)     /*!< in: number of pages to remove */
1541
1175
{
1542
1176
        buf_chunk_t*    chunks;
1543
1177
        buf_chunk_t*    chunk;
1546
1180
        buf_chunk_t*    max_chunk;
1547
1181
        buf_chunk_t*    max_free_chunk;
1548
1182
 
1549
 
        ut_ad(!buf_pool_mutex_own(buf_pool));
 
1183
        ut_ad(!buf_pool_mutex_own());
1550
1184
 
1551
1185
try_again:
1552
1186
        btr_search_disable(); /* Empty the adaptive hash index again */
1553
 
        buf_pool_mutex_enter(buf_pool);
 
1187
        buf_pool_mutex_enter();
1554
1188
 
1555
1189
shrink_again:
1556
1190
        if (buf_pool->n_chunks <= 1) {
1613
1247
 
1614
1248
                        mutex_enter(&block->mutex);
1615
1249
                        /* The following calls will temporarily
1616
 
                        release block->mutex and buf_pool->mutex.
 
1250
                        release block->mutex and buf_pool_mutex.
1617
1251
                        Therefore, we have to always retry,
1618
1252
                        even if !dirty && !nonfree. */
1619
1253
 
1629
1263
                        mutex_exit(&block->mutex);
1630
1264
                }
1631
1265
 
1632
 
                buf_pool_mutex_exit(buf_pool);
 
1266
                buf_pool_mutex_exit();
1633
1267
 
1634
1268
                /* Request for a flush of the chunk if it helps.
1635
1269
                Do not flush if there are non-free blocks, since
1638
1272
                        /* Avoid busy-waiting. */
1639
1273
                        os_thread_sleep(100000);
1640
1274
                } else if (dirty
1641
 
                           && buf_flush_LRU(buf_pool, dirty)
1642
 
                              == ULINT_UNDEFINED) {
 
1275
                           && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
 
1276
                           == ULINT_UNDEFINED) {
1643
1277
 
1644
 
                        buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
 
1278
                        buf_flush_wait_batch_end(BUF_FLUSH_LRU);
1645
1279
                }
1646
1280
 
1647
1281
                goto try_again;
1650
1284
        max_size = max_free_size;
1651
1285
        max_chunk = max_free_chunk;
1652
1286
 
1653
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1287
        srv_buf_pool_old_size = srv_buf_pool_size;
1654
1288
 
1655
1289
        /* Rewrite buf_pool->chunks.  Copy everything but max_chunk. */
1656
 
        chunks = static_cast<buf_chunk_t *>(mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks));
 
1290
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
1657
1291
        memcpy(chunks, buf_pool->chunks,
1658
1292
               (max_chunk - buf_pool->chunks) * sizeof *chunks);
1659
1293
        memcpy(chunks + (max_chunk - buf_pool->chunks),
1662
1296
               - (max_chunk + 1));
1663
1297
        ut_a(buf_pool->curr_size > max_chunk->size);
1664
1298
        buf_pool->curr_size -= max_chunk->size;
1665
 
        buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1299
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1666
1300
        chunk_size -= max_chunk->size;
1667
 
        buf_chunk_free(buf_pool, max_chunk);
 
1301
        buf_chunk_free(max_chunk);
1668
1302
        mem_free(buf_pool->chunks);
1669
1303
        buf_pool->chunks = chunks;
1670
1304
        buf_pool->n_chunks--;
1674
1308
 
1675
1309
                goto shrink_again;
1676
1310
        }
1677
 
        goto func_exit;
1678
1311
 
1679
1312
func_done:
1680
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1313
        srv_buf_pool_old_size = srv_buf_pool_size;
1681
1314
func_exit:
1682
 
        buf_pool_mutex_exit(buf_pool);
 
1315
        buf_pool_mutex_exit();
1683
1316
        btr_search_enable();
1684
1317
}
1685
1318
 
1686
1319
/********************************************************************//**
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 */
 
1320
Rebuild buf_pool->page_hash. */
 
1321
static
 
1322
void
 
1323
buf_pool_page_hash_rebuild(void)
 
1324
/*============================*/
1715
1325
{
1716
1326
        ulint           i;
1717
 
        buf_page_t*     b;
1718
 
        buf_chunk_t*    chunk;
1719
1327
        ulint           n_chunks;
 
1328
        buf_chunk_t*    chunk;
 
1329
        hash_table_t*   page_hash;
1720
1330
        hash_table_t*   zip_hash;
1721
 
        hash_table_t*   page_hash;
 
1331
        buf_page_t*     b;
1722
1332
 
1723
 
        buf_pool_mutex_enter(buf_pool);
 
1333
        buf_pool_mutex_enter();
1724
1334
 
1725
1335
        /* Free, create, and populate the hash table. */
1726
1336
        hash_table_free(buf_pool->page_hash);
1773
1383
                            buf_page_address_fold(b->space, b->offset), b);
1774
1384
        }
1775
1385
 
1776
 
        buf_flush_list_mutex_enter(buf_pool);
1777
1386
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1778
1387
             b = UT_LIST_GET_NEXT(list, b)) {
1779
1388
                ut_ad(b->in_flush_list);
1801
1410
                }
1802
1411
        }
1803
1412
 
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();
 
1413
        buf_pool_mutex_exit();
1978
1414
}
1979
1415
 
1980
1416
/********************************************************************//**
1984
1420
buf_pool_resize(void)
1985
1421
/*=================*/
1986
1422
{
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
 
 
 
1423
        buf_pool_mutex_enter();
 
1424
 
 
1425
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
 
1426
 
 
1427
                buf_pool_mutex_exit();
2025
1428
                return;
2026
1429
        }
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(
 
1430
 
 
1431
        if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
 
1432
 
 
1433
                buf_pool_mutex_exit();
 
1434
 
 
1435
                /* Disable adaptive hash indexes and empty the index
 
1436
                in order to free up memory in the buffer pool chunks. */
 
1437
                buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
 
1438
                                / UNIV_PAGE_SIZE);
 
1439
        } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
 
1440
 
 
1441
                /* Enlarge the buffer pool by at least one megabyte */
 
1442
 
 
1443
                ulint           mem_size
 
1444
                        = srv_buf_pool_size - srv_buf_pool_curr_size;
 
1445
                buf_chunk_t*    chunks;
 
1446
                buf_chunk_t*    chunk;
 
1447
 
 
1448
                chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
 
1449
 
 
1450
                memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
 
1451
                       * sizeof *chunks);
 
1452
 
 
1453
                chunk = &chunks[buf_pool->n_chunks];
 
1454
 
 
1455
                if (!buf_chunk_init(chunk, mem_size)) {
 
1456
                        mem_free(chunks);
 
1457
                } else {
 
1458
                        buf_pool->curr_size += chunk->size;
 
1459
                        srv_buf_pool_curr_size = buf_pool->curr_size
 
1460
                                * UNIV_PAGE_SIZE;
 
1461
                        mem_free(buf_pool->chunks);
 
1462
                        buf_pool->chunks = chunks;
 
1463
                        buf_pool->n_chunks++;
 
1464
                }
 
1465
 
 
1466
                srv_buf_pool_old_size = srv_buf_pool_size;
 
1467
                buf_pool_mutex_exit();
 
1468
        }
 
1469
 
 
1470
        buf_pool_page_hash_rebuild();
 
1471
}
 
1472
 
 
1473
/********************************************************************//**
 
1474
Moves the block to the start of the LRU list if there is a danger
 
1475
that the block would drift out of the buffer pool. */
 
1476
UNIV_INLINE
 
1477
void
 
1478
buf_block_make_young(
2059
1479
/*=================*/
2060
 
        ulint   space,  /*!< in: space id */
2061
 
        ulint   offset) /*!< in: page number */
 
1480
        buf_page_t*     bpage)  /*!< in: block to make younger */
2062
1481
{
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);
2085
 
                }
 
1482
        ut_ad(!buf_pool_mutex_own());
 
1483
 
 
1484
        /* Note that we read freed_page_clock's without holding any mutex:
 
1485
        this is allowed since the result is used only in heuristics */
 
1486
 
 
1487
        if (buf_page_peek_if_too_old(bpage)) {
 
1488
 
 
1489
                buf_pool_mutex_enter();
 
1490
                /* There has been freeing activity in the LRU list:
 
1491
                best to move to the head of the LRU list */
 
1492
 
 
1493
                buf_LRU_make_block_young(bpage);
 
1494
                buf_pool_mutex_exit();
2086
1495
        }
2087
 
 
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);
2118
1496
}
2119
1497
 
2120
1498
/********************************************************************//**
2121
1499
Moves a page to the start of the buffer pool LRU list. This high-level
2122
 
function can be used to prevent an important page from slipping out of
 
1500
function can be used to prevent an important page from from slipping out of
2123
1501
the buffer pool. */
2124
1502
UNIV_INTERN
2125
1503
void
2127
1505
/*================*/
2128
1506
        buf_page_t*     bpage)  /*!< in: buffer block of a file page */
2129
1507
{
2130
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2131
 
 
2132
 
        buf_pool_mutex_enter(buf_pool);
 
1508
        buf_pool_mutex_enter();
2133
1509
 
2134
1510
        ut_a(buf_page_in_file(bpage));
2135
1511
 
2136
1512
        buf_LRU_make_block_young(bpage);
2137
1513
 
2138
 
        buf_pool_mutex_exit(buf_pool);
2139
 
}
2140
 
 
2141
 
/********************************************************************//**
2142
 
Sets the time of the first access of a page and moves a page to the
2143
 
start of the buffer pool LRU list if it is too old.  This high-level
2144
 
function can be used to prevent an important page from slipping
2145
 
out of the buffer pool. */
2146
 
static
2147
 
void
2148
 
buf_page_set_accessed_make_young(
2149
 
/*=============================*/
2150
 
        buf_page_t*     bpage,          /*!< in/out: buffer block of a
2151
 
                                        file page */
2152
 
        unsigned        access_time)    /*!< in: bpage->access_time
2153
 
                                        read under mutex protection,
2154
 
                                        or 0 if unknown */
2155
 
{
2156
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2157
 
 
2158
 
        ut_ad(!buf_pool_mutex_own(buf_pool));
2159
 
        ut_a(buf_page_in_file(bpage));
2160
 
 
2161
 
        if (buf_page_peek_if_too_old(bpage)) {
2162
 
                buf_pool_mutex_enter(buf_pool);
2163
 
                buf_LRU_make_block_young(bpage);
2164
 
                buf_pool_mutex_exit(buf_pool);
2165
 
        } else if (!access_time) {
2166
 
                ulint   time_ms = ut_time_ms();
2167
 
                buf_pool_mutex_enter(buf_pool);
2168
 
                buf_page_set_accessed(bpage, time_ms);
2169
 
                buf_pool_mutex_exit(buf_pool);
2170
 
        }
 
1514
        buf_pool_mutex_exit();
2171
1515
}
2172
1516
 
2173
1517
/********************************************************************//**
2181
1525
        ulint   offset) /*!< in: page number */
2182
1526
{
2183
1527
        buf_block_t*    block;
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);
 
1528
 
 
1529
        buf_pool_mutex_enter();
 
1530
 
 
1531
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2189
1532
 
2190
1533
        if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
2191
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2192
1534
                block->check_index_page_at_flush = FALSE;
2193
1535
        }
2194
1536
 
2195
 
        buf_pool_mutex_exit(buf_pool);
 
1537
        buf_pool_mutex_exit();
2196
1538
}
2197
1539
 
2198
1540
/********************************************************************//**
2209
1551
{
2210
1552
        buf_block_t*    block;
2211
1553
        ibool           is_hashed;
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);
 
1554
 
 
1555
        buf_pool_mutex_enter();
 
1556
 
 
1557
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2217
1558
 
2218
1559
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2219
1560
                is_hashed = FALSE;
2220
1561
        } else {
2221
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2222
1562
                is_hashed = block->is_hashed;
2223
1563
        }
2224
1564
 
2225
 
        buf_pool_mutex_exit(buf_pool);
 
1565
        buf_pool_mutex_exit();
2226
1566
 
2227
1567
        return(is_hashed);
2228
1568
}
2242
1582
        ulint   offset) /*!< in: page number */
2243
1583
{
2244
1584
        buf_page_t*     bpage;
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);
 
1585
 
 
1586
        buf_pool_mutex_enter();
 
1587
 
 
1588
        bpage = buf_page_hash_get(space, offset);
2250
1589
 
2251
1590
        if (bpage) {
2252
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2253
1591
                bpage->file_page_was_freed = TRUE;
2254
1592
        }
2255
1593
 
2256
 
        buf_pool_mutex_exit(buf_pool);
 
1594
        buf_pool_mutex_exit();
2257
1595
 
2258
1596
        return(bpage);
2259
1597
}
2272
1610
        ulint   offset) /*!< in: page number */
2273
1611
{
2274
1612
        buf_page_t*     bpage;
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);
 
1613
 
 
1614
        buf_pool_mutex_enter();
 
1615
 
 
1616
        bpage = buf_page_hash_get(space, offset);
2280
1617
 
2281
1618
        if (bpage) {
2282
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2283
1619
                bpage->file_page_was_freed = FALSE;
2284
1620
        }
2285
1621
 
2286
 
        buf_pool_mutex_exit(buf_pool);
 
1622
        buf_pool_mutex_exit();
2287
1623
 
2288
1624
        return(bpage);
2289
1625
}
2309
1645
        buf_page_t*     bpage;
2310
1646
        mutex_t*        block_mutex;
2311
1647
        ibool           must_read;
2312
 
        unsigned        access_time;
2313
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2314
1648
 
2315
1649
#ifndef UNIV_LOG_DEBUG
2316
1650
        ut_ad(!ibuf_inside());
2317
1651
#endif
2318
 
        buf_pool->stat.n_page_gets++;
 
1652
        buf_pool->n_page_gets++;
2319
1653
 
2320
1654
        for (;;) {
2321
 
                buf_pool_mutex_enter(buf_pool);
 
1655
                buf_pool_mutex_enter();
2322
1656
lookup:
2323
 
                bpage = buf_page_hash_get(buf_pool, space, offset);
 
1657
                bpage = buf_page_hash_get(space, offset);
2324
1658
                if (bpage) {
2325
 
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2326
1659
                        break;
2327
1660
                }
2328
1661
 
2329
1662
                /* Page not in buf_pool: needs to be read from file */
2330
1663
 
2331
 
                buf_pool_mutex_exit(buf_pool);
 
1664
                buf_pool_mutex_exit();
2332
1665
 
2333
1666
                buf_read_page(space, zip_size, offset);
2334
1667
 
2340
1673
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
2341
1674
                /* There is no compressed page. */
2342
1675
err_exit:
2343
 
                buf_pool_mutex_exit(buf_pool);
 
1676
                buf_pool_mutex_exit();
2344
1677
                return(NULL);
2345
1678
        }
2346
1679
 
2347
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2348
 
 
2349
1680
        switch (buf_page_get_state(bpage)) {
2350
1681
        case BUF_BLOCK_NOT_USED:
2351
1682
        case BUF_BLOCK_READY_FOR_USE:
2355
1686
                break;
2356
1687
        case BUF_BLOCK_ZIP_PAGE:
2357
1688
        case BUF_BLOCK_ZIP_DIRTY:
2358
 
                block_mutex = &buf_pool->zip_mutex;
 
1689
                block_mutex = &buf_pool_zip_mutex;
2359
1690
                mutex_enter(block_mutex);
2360
1691
                bpage->buf_fix_count++;
2361
1692
                goto got_block;
2381
1712
 
2382
1713
got_block:
2383
1714
        must_read = buf_page_get_io_fix(bpage) == BUF_IO_READ;
2384
 
        access_time = buf_page_is_accessed(bpage);
2385
 
 
2386
 
        buf_pool_mutex_exit(buf_pool);
 
1715
 
 
1716
        buf_pool_mutex_exit();
 
1717
 
 
1718
        buf_page_set_accessed(bpage, TRUE);
2387
1719
 
2388
1720
        mutex_exit(block_mutex);
2389
1721
 
2390
 
        buf_page_set_accessed_make_young(bpage, access_time);
 
1722
        buf_block_make_young(bpage);
2391
1723
 
2392
1724
#ifdef UNIV_DEBUG_FILE_ACCESSES
2393
1725
        ut_a(!bpage->file_page_was_freed);
2455
1787
        buf_block_t*    block,  /*!< in/out: block */
2456
1788
        ibool           check)  /*!< in: TRUE=verify the page checksum */
2457
1789
{
2458
 
        const byte*     frame           = block->page.zip.data;
2459
 
        ulint           stamp_checksum  = mach_read_from_4(
2460
 
                frame + FIL_PAGE_SPACE_OR_CHKSUM);
 
1790
        const byte* frame = block->page.zip.data;
2461
1791
 
2462
1792
        ut_ad(buf_block_get_zip_size(block));
2463
1793
        ut_a(buf_block_get_space(block) != 0);
2464
1794
 
2465
 
        if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
 
1795
        if (UNIV_LIKELY(check)) {
 
1796
                ulint   stamp_checksum  = mach_read_from_4(
 
1797
                        frame + FIL_PAGE_SPACE_OR_CHKSUM);
2466
1798
                ulint   calc_checksum   = page_zip_calc_checksum(
2467
1799
                        frame, page_zip_get_size(&block->page.zip));
2468
1800
 
2480
1812
        switch (fil_page_get_type(frame)) {
2481
1813
        case FIL_PAGE_INDEX:
2482
1814
                if (page_zip_decompress(&block->page.zip,
2483
 
                                        block->frame, TRUE)) {
 
1815
                                        block->frame)) {
2484
1816
                        return(TRUE);
2485
1817
                }
2486
1818
 
2513
1845
 
2514
1846
#ifndef UNIV_HOTBACKUP
2515
1847
/*******************************************************************//**
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
 
1848
Gets the block to whose frame the pointer is pointing to.
 
1849
@return pointer to block, never NULL */
 
1850
UNIV_INTERN
2520
1851
buf_block_t*
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 */
 
1852
buf_block_align(
 
1853
/*============*/
 
1854
        const byte*     ptr)    /*!< in: pointer to a frame */
2526
1855
{
2527
1856
        buf_chunk_t*    chunk;
2528
1857
        ulint           i;
2548
1877
                        ut_ad(block->frame == page_align(ptr));
2549
1878
#ifdef UNIV_DEBUG
2550
1879
                        /* A thread that updates these fields must
2551
 
                        hold buf_pool->mutex and block->mutex.  Acquire
 
1880
                        hold buf_pool_mutex and block->mutex.  Acquire
2552
1881
                        only the latter. */
2553
1882
                        mutex_enter(&block->mutex);
2554
1883
 
2597
1926
                }
2598
1927
        }
2599
1928
 
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
 
 
2624
1929
        /* The block should always be found. */
2625
1930
        ut_error;
2626
1931
        return(NULL);
2628
1933
 
2629
1934
/********************************************************************//**
2630
1935
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
2631
 
the buf_block_t itself or a member of it. This functions checks one of
2632
 
the buffer pool instances.
 
1936
the buf_block_t itself or a member of it
2633
1937
@return TRUE if ptr belongs to a buf_block_t struct */
2634
 
static
 
1938
UNIV_INTERN
2635
1939
ibool
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 */
 
1940
buf_pointer_is_block_field(
 
1941
/*=======================*/
 
1942
        const void*             ptr)    /*!< in: pointer not
 
1943
                                        dereferenced */
2640
1944
{
2641
1945
        const buf_chunk_t*              chunk   = buf_pool->chunks;
2642
1946
        const buf_chunk_t* const        echunk  = chunk + buf_pool->n_chunks;
2657
1961
}
2658
1962
 
2659
1963
/********************************************************************//**
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
 
/********************************************************************//**
2685
1964
Find out if a buffer block was created by buf_chunk_init().
2686
1965
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
2687
1966
static
2688
1967
ibool
2689
1968
buf_block_is_uncompressed(
2690
1969
/*======================*/
2691
 
        buf_pool_t*             buf_pool,       /*!< in: buffer pool instance */
2692
 
        const buf_block_t*      block)          /*!< in: pointer to block,
2693
 
                                                not dereferenced */
 
1970
        const buf_block_t*      block)  /*!< in: pointer to block,
 
1971
                                        not dereferenced */
2694
1972
{
2695
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1973
        ut_ad(buf_pool_mutex_own());
2696
1974
 
2697
1975
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2698
1976
                /* The pointer should be aligned. */
2699
1977
                return(FALSE);
2700
1978
        }
2701
1979
 
2702
 
        return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
 
1980
        return(buf_pointer_is_block_field((void *)block));
2703
1981
}
2704
1982
 
2705
1983
/********************************************************************//**
2716
1994
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2717
1995
        buf_block_t*    guess,  /*!< in: guessed block or NULL */
2718
1996
        ulint           mode,   /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2719
 
                                BUF_GET_NO_LATCH, or
2720
 
                                BUF_GET_IF_IN_POOL_OR_WATCH */
 
1997
                                BUF_GET_NO_LATCH */
2721
1998
        const char*     file,   /*!< in: file name */
2722
1999
        ulint           line,   /*!< in: line where called */
2723
2000
        mtr_t*          mtr)    /*!< in: mini-transaction */
2724
2001
{
2725
2002
        buf_block_t*    block;
2726
 
        ulint           fold;
2727
 
        unsigned        access_time;
 
2003
        ibool           accessed;
2728
2004
        ulint           fix_type;
2729
2005
        ibool           must_read;
2730
 
        ulint           retries = 0;
2731
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2732
2006
 
2733
2007
        ut_ad(mtr);
2734
 
        ut_ad(mtr->state == MTR_ACTIVE);
2735
2008
        ut_ad((rw_latch == RW_S_LATCH)
2736
2009
              || (rw_latch == RW_X_LATCH)
2737
2010
              || (rw_latch == RW_NO_LATCH));
2738
2011
        ut_ad((mode != BUF_GET_NO_LATCH) || (rw_latch == RW_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);
 
2012
        ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
 
2013
              || (mode == BUF_GET_NO_LATCH));
2743
2014
        ut_ad(zip_size == fil_space_get_zip_size(space));
2744
2015
        ut_ad(ut_is_2pow(zip_size));
2745
2016
#ifndef UNIV_LOG_DEBUG
2746
2017
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
2747
2018
#endif
2748
 
        buf_pool->stat.n_page_gets++;
2749
 
        fold = buf_page_address_fold(space, offset);
 
2019
        buf_pool->n_page_gets++;
2750
2020
loop:
2751
2021
        block = guess;
2752
 
        buf_pool_mutex_enter(buf_pool);
 
2022
        buf_pool_mutex_enter();
2753
2023
 
2754
2024
        if (block) {
2755
2025
                /* If the guess is a compressed page descriptor that
2760
2030
                the guess may be pointing to a buffer pool chunk that
2761
2031
                has been released when resizing the buffer pool. */
2762
2032
 
2763
 
                if (!buf_block_is_uncompressed(buf_pool, block)
 
2033
                if (!buf_block_is_uncompressed(block)
2764
2034
                    || offset != block->page.offset
2765
2035
                    || space != block->page.space
2766
2036
                    || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2773
2043
        }
2774
2044
 
2775
2045
        if (block == NULL) {
2776
 
                block = (buf_block_t*) buf_page_hash_get_low(
2777
 
                        buf_pool, space, offset, fold);
 
2046
                block = (buf_block_t*) buf_page_hash_get(space, offset);
2778
2047
        }
2779
2048
 
2780
2049
loop2:
2781
 
        if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2782
 
                block = NULL;
2783
 
        }
2784
 
 
2785
2050
        if (block == NULL) {
2786
2051
                /* Page not in buf_pool: needs to be read from file */
2787
2052
 
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) {
 
2053
                buf_pool_mutex_exit();
 
2054
 
 
2055
                if (mode == BUF_GET_IF_IN_POOL) {
2802
2056
 
2803
2057
                        return(NULL);
2804
2058
                }
2805
2059
 
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
 
                }
 
2060
                buf_read_page(space, zip_size, offset);
2829
2061
 
2830
2062
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2831
2063
                ut_a(++buf_dbg_counter % 37 || buf_validate());
2833
2065
                goto loop;
2834
2066
        }
2835
2067
 
2836
 
got_block:
2837
2068
        ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
2838
2069
 
2839
2070
        must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
2840
2071
 
2841
2072
        if (must_read && mode == BUF_GET_IF_IN_POOL) {
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);
 
2073
                /* The page is only being read to buffer */
 
2074
                buf_pool_mutex_exit();
2847
2075
 
2848
2076
                return(NULL);
2849
2077
        }
2859
2087
        case BUF_BLOCK_ZIP_DIRTY:
2860
2088
                bpage = &block->page;
2861
2089
                /* Protect bpage->buf_fix_count. */
2862
 
                mutex_enter(&buf_pool->zip_mutex);
 
2090
                mutex_enter(&buf_pool_zip_mutex);
2863
2091
 
2864
2092
                if (bpage->buf_fix_count
2865
2093
                    || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2866
2094
                        /* This condition often occurs when the buffer
2867
2095
                        is not buffer-fixed, but I/O-fixed by
2868
2096
                        buf_page_init_for_read(). */
2869
 
                        mutex_exit(&buf_pool->zip_mutex);
 
2097
                        mutex_exit(&buf_pool_zip_mutex);
2870
2098
wait_until_unfixed:
2871
2099
                        /* The block is buffer-fixed or I/O-fixed.
2872
2100
                        Try again later. */
2873
 
                        buf_pool_mutex_exit(buf_pool);
 
2101
                        buf_pool_mutex_exit();
2874
2102
                        os_thread_sleep(WAIT_FOR_READ);
2875
 
  
 
2103
 
2876
2104
                        goto loop;
2877
2105
                }
2878
2106
 
2879
2107
                /* Allocate an uncompressed page. */
2880
 
                buf_pool_mutex_exit(buf_pool);
2881
 
                mutex_exit(&buf_pool->zip_mutex);
 
2108
                buf_pool_mutex_exit();
 
2109
                mutex_exit(&buf_pool_zip_mutex);
2882
2110
 
2883
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2111
                block = buf_LRU_get_free_block(0);
2884
2112
                ut_a(block);
2885
2113
 
2886
 
                buf_pool_mutex_enter(buf_pool);
 
2114
                buf_pool_mutex_enter();
2887
2115
                mutex_enter(&block->mutex);
2888
2116
 
2889
2117
                {
2890
 
                        buf_page_t*     hash_bpage;
2891
 
 
2892
 
                        hash_bpage = buf_page_hash_get_low(
2893
 
                                buf_pool, space, offset, fold);
 
2118
                        buf_page_t*     hash_bpage
 
2119
                                = buf_page_hash_get(space, offset);
2894
2120
 
2895
2121
                        if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2896
2122
                                /* The buf_pool->page_hash was modified
2897
 
                                while buf_pool->mutex was released.
 
2123
                                while buf_pool_mutex was released.
2898
2124
                                Free the block that was allocated. */
2899
2125
 
2900
2126
                                buf_LRU_block_free_non_file_page(block);
2910
2136
                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
2911
2137
 
2912
2138
                        /* The block was buffer-fixed or I/O-fixed
2913
 
                        while buf_pool->mutex was not held by this thread.
 
2139
                        while buf_pool_mutex was not held by this thread.
2914
2140
                        Free the block that was allocated and try again.
2915
2141
                        This should be extremely unlikely. */
2916
2142
 
2923
2149
                /* Move the compressed page from bpage to block,
2924
2150
                and uncompress it. */
2925
2151
 
2926
 
                mutex_enter(&buf_pool->zip_mutex);
 
2152
                mutex_enter(&buf_pool_zip_mutex);
2927
2153
 
2928
2154
                buf_relocate(bpage, &block->page);
2929
2155
                buf_block_init_low(block);
2939
2165
                        ut_ad(!block->page.in_flush_list);
2940
2166
                } else {
2941
2167
                        /* Relocate buf_pool->flush_list. */
2942
 
                        buf_flush_relocate_on_flush_list(bpage,
2943
 
                                                         &block->page);
 
2168
                        buf_page_t*     b;
 
2169
 
 
2170
                        b = UT_LIST_GET_PREV(list, &block->page);
 
2171
                        ut_ad(block->page.in_flush_list);
 
2172
                        UT_LIST_REMOVE(list, buf_pool->flush_list,
 
2173
                                       &block->page);
 
2174
 
 
2175
                        if (b) {
 
2176
                                UT_LIST_INSERT_AFTER(
 
2177
                                        list, buf_pool->flush_list, b,
 
2178
                                        &block->page);
 
2179
                        } else {
 
2180
                                UT_LIST_ADD_FIRST(
 
2181
                                        list, buf_pool->flush_list,
 
2182
                                        &block->page);
 
2183
                        }
2944
2184
                }
2945
2185
 
2946
2186
                /* Buffer-fix, I/O-fix, and X-latch the block
2953
2193
 
2954
2194
                block->page.buf_fix_count = 1;
2955
2195
                buf_block_set_io_fix(block, BUF_IO_READ);
2956
 
                rw_lock_x_lock_func(&block->lock, 0, file, line);
2957
 
 
2958
 
                UNIV_MEM_INVALID(bpage, sizeof *bpage);
2959
 
 
 
2196
                rw_lock_x_lock(&block->lock);
2960
2197
                mutex_exit(&block->mutex);
2961
 
                mutex_exit(&buf_pool->zip_mutex);
 
2198
                mutex_exit(&buf_pool_zip_mutex);
2962
2199
                buf_pool->n_pend_unzip++;
2963
2200
 
2964
 
                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
 
2201
                buf_buddy_free(bpage, sizeof *bpage);
2965
2202
 
2966
 
                buf_pool_mutex_exit(buf_pool);
 
2203
                buf_pool_mutex_exit();
2967
2204
 
2968
2205
                /* Decompress the page and apply buffered operations
2969
 
                while not holding buf_pool->mutex or block->mutex. */
 
2206
                while not holding buf_pool_mutex or block->mutex. */
2970
2207
                success = buf_zip_decompress(block, srv_use_checksums);
2971
 
                ut_a(success);
2972
2208
 
2973
 
                if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
 
2209
                if (UNIV_LIKELY(success)) {
2974
2210
                        ibuf_merge_or_delete_for_page(block, space, offset,
2975
2211
                                                      zip_size, TRUE);
2976
2212
                }
2977
2213
 
2978
2214
                /* Unfix and unlatch the block. */
2979
 
                buf_pool_mutex_enter(buf_pool);
 
2215
                buf_pool_mutex_enter();
2980
2216
                mutex_enter(&block->mutex);
2981
2217
                block->page.buf_fix_count--;
2982
2218
                buf_block_set_io_fix(block, BUF_IO_NONE);
2984
2220
                buf_pool->n_pend_unzip--;
2985
2221
                rw_lock_x_unlock(&block->lock);
2986
2222
 
 
2223
                if (UNIV_UNLIKELY(!success)) {
 
2224
 
 
2225
                        buf_pool_mutex_exit();
 
2226
                        return(NULL);
 
2227
                }
 
2228
 
2987
2229
                break;
2988
2230
 
2989
2231
        case BUF_BLOCK_ZIP_FREE:
2998
2240
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2999
2241
 
3000
2242
        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. */
3005
2243
        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 */
3047
2244
 
3048
2245
        buf_block_buf_fix_inc(block, file, line);
 
2246
        buf_pool_mutex_exit();
 
2247
 
 
2248
        /* Check if this is the first access to the page */
 
2249
 
 
2250
        accessed = buf_page_is_accessed(&block->page);
 
2251
 
 
2252
        buf_page_set_accessed(&block->page, TRUE);
3049
2253
 
3050
2254
        mutex_exit(&block->mutex);
3051
2255
 
3052
 
        /* Check if this is the first access to the page */
3053
 
 
3054
 
        access_time = buf_page_is_accessed(&block->page);
3055
 
 
3056
 
        buf_pool_mutex_exit(buf_pool);
3057
 
 
3058
 
        buf_page_set_accessed_make_young(&block->page, access_time);
 
2256
        buf_block_make_young(&block->page);
3059
2257
 
3060
2258
#ifdef UNIV_DEBUG_FILE_ACCESSES
3061
2259
        ut_a(!block->page.file_page_was_freed);
3108
2306
 
3109
2307
        mtr_memo_push(mtr, block, fix_type);
3110
2308
 
3111
 
        if (!access_time) {
 
2309
        if (!accessed) {
3112
2310
                /* In the case of a first access, try to apply linear
3113
2311
                read-ahead */
3114
2312
 
3128
2326
@return TRUE if success */
3129
2327
UNIV_INTERN
3130
2328
ibool
3131
 
buf_page_optimistic_get(
3132
 
/*====================*/
 
2329
buf_page_optimistic_get_func(
 
2330
/*=========================*/
3133
2331
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
3134
2332
        buf_block_t*    block,  /*!< in: guessed buffer block */
3135
2333
        ib_uint64_t     modify_clock,/*!< in: modify clock value if mode is
3138
2336
        ulint           line,   /*!< in: line where called */
3139
2337
        mtr_t*          mtr)    /*!< in: mini-transaction */
3140
2338
{
3141
 
        buf_pool_t*     buf_pool;
3142
 
        unsigned        access_time;
 
2339
        ibool           accessed;
3143
2340
        ibool           success;
3144
2341
        ulint           fix_type;
3145
2342
 
3146
 
        ut_ad(block);
3147
 
        ut_ad(mtr);
3148
 
        ut_ad(mtr->state == MTR_ACTIVE);
 
2343
        ut_ad(mtr && block);
3149
2344
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3150
2345
 
3151
2346
        mutex_enter(&block->mutex);
3158
2353
        }
3159
2354
 
3160
2355
        buf_block_buf_fix_inc(block, file, line);
 
2356
        accessed = buf_page_is_accessed(&block->page);
 
2357
        buf_page_set_accessed(&block->page, TRUE);
3161
2358
 
3162
2359
        mutex_exit(&block->mutex);
3163
2360
 
3164
 
        /* Check if this is the first access to the page.
3165
 
        We do a dirty read on purpose, to avoid mutex contention.
3166
 
        This field is only used for heuristic purposes; it does not
3167
 
        affect correctness. */
 
2361
        buf_block_make_young(&block->page);
3168
2362
 
3169
 
        access_time = buf_page_is_accessed(&block->page);
3170
 
        buf_page_set_accessed_make_young(&block->page, access_time);
 
2363
        /* Check if this is the first access to the page */
3171
2364
 
3172
2365
        ut_ad(!ibuf_inside()
3173
2366
              || ibuf_page(buf_block_get_space(block),
3219
2412
#ifdef UNIV_DEBUG_FILE_ACCESSES
3220
2413
        ut_a(block->page.file_page_was_freed == FALSE);
3221
2414
#endif
3222
 
        if (UNIV_UNLIKELY(!access_time)) {
 
2415
        if (UNIV_UNLIKELY(!accessed)) {
3223
2416
                /* In the case of a first access, try to apply linear
3224
2417
                read-ahead */
3225
2418
 
3232
2425
        ut_a(ibuf_count_get(buf_block_get_space(block),
3233
2426
                            buf_block_get_page_no(block)) == 0);
3234
2427
#endif
3235
 
        buf_pool = buf_pool_from_block(block);
3236
 
        buf_pool->stat.n_page_gets++;
 
2428
        buf_pool->n_page_gets++;
3237
2429
 
3238
2430
        return(TRUE);
3239
2431
}
3254
2446
        ulint           line,   /*!< in: line where called */
3255
2447
        mtr_t*          mtr)    /*!< in: mini-transaction */
3256
2448
{
3257
 
        buf_pool_t*     buf_pool;
3258
2449
        ibool           success;
3259
2450
        ulint           fix_type;
3260
2451
 
3261
2452
        ut_ad(mtr);
3262
 
        ut_ad(mtr->state == MTR_ACTIVE);
3263
2453
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3264
2454
 
3265
2455
        mutex_enter(&block->mutex);
3283
2473
 
3284
2474
        mutex_exit(&block->mutex);
3285
2475
 
3286
 
        buf_pool = buf_pool_from_block(block);
3287
 
 
3288
 
        if (mode == BUF_MAKE_YOUNG && buf_page_peek_if_too_old(&block->page)) {
3289
 
                buf_pool_mutex_enter(buf_pool);
3290
 
                buf_LRU_make_block_young(&block->page);
3291
 
                buf_pool_mutex_exit(buf_pool);
3292
 
        } else if (!buf_page_is_accessed(&block->page)) {
3293
 
                /* Above, we do a dirty read on purpose, to avoid
3294
 
                mutex contention.  The field buf_page_t::access_time
3295
 
                is only used for heuristic purposes.  Writes to the
3296
 
                field must be protected by mutex, however. */
3297
 
                ulint   time_ms = ut_time_ms();
3298
 
 
3299
 
                buf_pool_mutex_enter(buf_pool);
3300
 
                buf_page_set_accessed(&block->page, time_ms);
3301
 
                buf_pool_mutex_exit(buf_pool);
 
2476
        if (mode == BUF_MAKE_YOUNG) {
 
2477
                buf_block_make_young(&block->page);
3302
2478
        }
3303
2479
 
3304
2480
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
3337
2513
             || (ibuf_count_get(buf_block_get_space(block),
3338
2514
                                buf_block_get_page_no(block)) == 0));
3339
2515
#endif
3340
 
        buf_pool->stat.n_page_gets++;
 
2516
        buf_pool->n_page_gets++;
3341
2517
 
3342
2518
        return(TRUE);
3343
2519
}
3360
2536
        buf_block_t*    block;
3361
2537
        ibool           success;
3362
2538
        ulint           fix_type;
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);
 
2539
 
 
2540
        buf_pool_mutex_enter();
 
2541
        block = buf_block_hash_get(space_id, page_no);
 
2542
 
 
2543
        if (!block) {
 
2544
                buf_pool_mutex_exit();
3373
2545
                return(NULL);
3374
2546
        }
3375
2547
 
3376
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
3377
 
 
3378
2548
        mutex_enter(&block->mutex);
3379
 
        buf_pool_mutex_exit(buf_pool);
 
2549
        buf_pool_mutex_exit();
3380
2550
 
3381
2551
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3382
2552
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3419
2589
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3420
2590
        buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
3421
2591
 
3422
 
        buf_pool->stat.n_page_gets++;
 
2592
        buf_pool->n_page_gets++;
3423
2593
 
3424
2594
#ifdef UNIV_IBUF_COUNT_DEBUG
3425
2595
        ut_a(ibuf_count_get(buf_block_get_space(block),
3438
2608
        buf_page_t*     bpage)  /*!< in: block to init */
3439
2609
{
3440
2610
        bpage->flush_type = BUF_FLUSH_LRU;
 
2611
        bpage->accessed = FALSE;
3441
2612
        bpage->io_fix = BUF_IO_NONE;
3442
2613
        bpage->buf_fix_count = 0;
3443
2614
        bpage->freed_page_clock = 0;
3444
 
        bpage->access_time = 0;
3445
2615
        bpage->newest_modification = 0;
3446
2616
        bpage->oldest_modification = 0;
3447
2617
        HASH_INVALIDATE(bpage, hash);
3459
2629
        ulint           space,  /*!< in: space id */
3460
2630
        ulint           offset, /*!< in: offset of the page within space
3461
2631
                                in units of a page */
3462
 
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
3463
2632
        buf_block_t*    block)  /*!< in: block to init */
3464
2633
{
3465
2634
        buf_page_t*     hash_page;
3466
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3467
2635
 
3468
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2636
        ut_ad(buf_pool_mutex_own());
3469
2637
        ut_ad(mutex_own(&(block->mutex)));
3470
2638
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
3471
2639
 
3483
2651
 
3484
2652
        buf_block_init_low(block);
3485
2653
 
3486
 
        block->lock_hash_val = lock_rec_hash(space, offset);
3487
 
 
3488
 
        buf_page_init_low(&block->page);
 
2654
        block->lock_hash_val    = lock_rec_hash(space, offset);
3489
2655
 
3490
2656
        /* Insert into the hash table of file pages */
3491
2657
 
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 {
 
2658
        hash_page = buf_page_hash_get(space, offset);
 
2659
 
 
2660
        if (UNIV_LIKELY_NULL(hash_page)) {
3503
2661
                fprintf(stderr,
3504
2662
                        "InnoDB: Error: page %lu %lu already found"
3505
2663
                        " in the hash table: %p, %p\n",
3508
2666
                        (const void*) hash_page, (const void*) block);
3509
2667
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3510
2668
                mutex_exit(&block->mutex);
3511
 
                buf_pool_mutex_exit(buf_pool);
 
2669
                buf_pool_mutex_exit();
3512
2670
                buf_print();
3513
2671
                buf_LRU_print();
3514
2672
                buf_validate();
3517
2675
                ut_error;
3518
2676
        }
3519
2677
 
 
2678
        buf_page_init_low(&block->page);
 
2679
 
3520
2680
        ut_ad(!block->page.in_zip_hash);
3521
2681
        ut_ad(!block->page.in_page_hash);
3522
2682
        ut_d(block->page.in_page_hash = TRUE);
3523
2683
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
3524
 
                    fold, &block->page);
 
2684
                    buf_page_address_fold(space, offset), &block->page);
3525
2685
}
3526
2686
 
3527
2687
/********************************************************************//**
3543
2703
        ulint           space,  /*!< in: space id */
3544
2704
        ulint           zip_size,/*!< in: compressed page size, or 0 */
3545
2705
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
3546
 
        ib_int64_t      tablespace_version,
3547
 
                                /*!< in: prevents reading from a wrong
 
2706
        ib_int64_t      tablespace_version,/*!< in: prevents reading from a wrong
3548
2707
                                version of the tablespace in case we have done
3549
2708
                                DISCARD + IMPORT */
3550
2709
        ulint           offset) /*!< in: page number */
3551
2710
{
3552
2711
        buf_block_t*    block;
3553
 
        buf_page_t*     bpage   = NULL;
3554
 
        buf_page_t*     watch_page;
 
2712
        buf_page_t*     bpage;
3555
2713
        mtr_t           mtr;
3556
 
        ulint           fold;
3557
2714
        ibool           lru     = FALSE;
3558
2715
        void*           data;
3559
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3560
2716
 
3561
2717
        ut_ad(buf_pool);
3562
2718
 
3585
2741
            && UNIV_LIKELY(!recv_recovery_is_on())) {
3586
2742
                block = NULL;
3587
2743
        } else {
3588
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2744
                block = buf_LRU_get_free_block(0);
3589
2745
                ut_ad(block);
3590
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
3591
2746
        }
3592
2747
 
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)) {
 
2748
        buf_pool_mutex_enter();
 
2749
 
 
2750
        if (buf_page_hash_get(space, offset)) {
3599
2751
                /* The page is already in the buffer pool. */
3600
 
                watch_page = NULL;
3601
2752
err_exit:
3602
2753
                if (block) {
3603
2754
                        mutex_enter(&block->mutex);
3621
2772
        if (block) {
3622
2773
                bpage = &block->page;
3623
2774
                mutex_enter(&block->mutex);
3624
 
 
3625
 
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
3626
 
 
3627
 
                buf_page_init(space, offset, fold, block);
 
2775
                buf_page_init(space, offset, block);
3628
2776
 
3629
2777
                /* The block must be put to the LRU list, to the old blocks */
3630
2778
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3644
2792
                if (UNIV_UNLIKELY(zip_size)) {
3645
2793
                        page_zip_set_size(&block->page.zip, zip_size);
3646
2794
 
3647
 
                        /* buf_pool->mutex may be released and
 
2795
                        /* buf_pool_mutex may be released and
3648
2796
                        reacquired by buf_buddy_alloc().  Thus, we
3649
2797
                        must release block->mutex in order not to
3650
2798
                        break the latching order in the reacquisition
3651
 
                        of buf_pool->mutex.  We also must defer this
 
2799
                        of buf_pool_mutex.  We also must defer this
3652
2800
                        operation until after the block descriptor has
3653
2801
                        been added to buf_pool->LRU and
3654
2802
                        buf_pool->page_hash. */
3655
2803
                        mutex_exit(&block->mutex);
3656
 
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2804
                        data = buf_buddy_alloc(zip_size, &lru);
3657
2805
                        mutex_enter(&block->mutex);
3658
 
                        block->page.zip.data = static_cast<unsigned char *>(data);
 
2806
                        block->page.zip.data = data;
3659
2807
 
3660
2808
                        /* To maintain the invariant
3661
2809
                        block->in_unzip_LRU_list
3677
2825
                control block (bpage), in order to avoid the
3678
2826
                invocation of buf_buddy_relocate_block() on
3679
2827
                uninitialized data. */
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);
 
2828
                data = buf_buddy_alloc(zip_size, &lru);
 
2829
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3685
2830
 
3686
2831
                /* If buf_buddy_alloc() allocated storage from the LRU list,
3687
 
                it released and reacquired buf_pool->mutex.  Thus, we must
 
2832
                it released and reacquired buf_pool_mutex.  Thus, we must
3688
2833
                check the page_hash again, as it may have been modified. */
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
 
                        }
 
2834
                if (UNIV_UNLIKELY(lru)
 
2835
                    && UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
 
2836
 
 
2837
                        /* The block was added by some other thread. */
 
2838
                        buf_buddy_free(bpage, sizeof *bpage);
 
2839
                        buf_buddy_free(data, zip_size);
 
2840
 
 
2841
                        bpage = NULL;
 
2842
                        goto func_exit;
3706
2843
                }
3707
2844
 
3708
2845
                page_zip_des_init(&bpage->zip);
3709
2846
                page_zip_set_size(&bpage->zip, zip_size);
3710
 
                bpage->zip.data = static_cast<unsigned char *>(data);
 
2847
                bpage->zip.data = data;
3711
2848
 
3712
 
                mutex_enter(&buf_pool->zip_mutex);
 
2849
                mutex_enter(&buf_pool_zip_mutex);
3713
2850
                UNIV_MEM_DESC(bpage->zip.data,
3714
2851
                              page_zip_get_size(&bpage->zip), bpage);
3715
 
 
3716
2852
                buf_page_init_low(bpage);
3717
 
 
3718
2853
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
3719
2854
                bpage->space    = space;
3720
2855
                bpage->offset   = offset;
3721
2856
 
3722
 
 
3723
2857
#ifdef UNIV_DEBUG
3724
2858
                bpage->in_page_hash = FALSE;
3725
2859
                bpage->in_zip_hash = FALSE;
3729
2863
#endif /* UNIV_DEBUG */
3730
2864
 
3731
2865
                ut_d(bpage->in_page_hash = TRUE);
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);
 
2866
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
2867
                            buf_page_address_fold(space, offset), bpage);
3744
2868
 
3745
2869
                /* The block must be put to the LRU list, to the old blocks */
3746
2870
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3748
2872
 
3749
2873
                buf_page_set_io_fix(bpage, BUF_IO_READ);
3750
2874
 
3751
 
                mutex_exit(&buf_pool->zip_mutex);
 
2875
                mutex_exit(&buf_pool_zip_mutex);
3752
2876
        }
3753
2877
 
3754
2878
        buf_pool->n_pend_reads++;
3755
2879
func_exit:
3756
 
        buf_pool_mutex_exit(buf_pool);
 
2880
        buf_pool_mutex_exit();
3757
2881
 
3758
2882
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
3759
2883
 
3782
2906
{
3783
2907
        buf_frame_t*    frame;
3784
2908
        buf_block_t*    block;
3785
 
        ulint           fold;
3786
2909
        buf_block_t*    free_block      = NULL;
3787
 
        ulint           time_ms         = ut_time_ms();
3788
 
        buf_pool_t*     buf_pool        = buf_pool_get(space, offset);
3789
2910
 
3790
2911
        ut_ad(mtr);
3791
 
        ut_ad(mtr->state == MTR_ACTIVE);
3792
2912
        ut_ad(space || !zip_size);
3793
2913
 
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)) {
 
2914
        free_block = buf_LRU_get_free_block(0);
 
2915
 
 
2916
        buf_pool_mutex_enter();
 
2917
 
 
2918
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2919
 
 
2920
        if (block && buf_page_in_file(&block->page)) {
3806
2921
#ifdef UNIV_IBUF_COUNT_DEBUG
3807
2922
                ut_a(ibuf_count_get(space, offset) == 0);
3808
2923
#endif
3811
2926
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3812
2927
 
3813
2928
                /* Page can be found in buf_pool */
3814
 
                buf_pool_mutex_exit(buf_pool);
 
2929
                buf_pool_mutex_exit();
3815
2930
 
3816
2931
                buf_block_free(free_block);
3817
2932
 
3832
2947
 
3833
2948
        mutex_enter(&block->mutex);
3834
2949
 
3835
 
        buf_page_init(space, offset, fold, block);
 
2950
        buf_page_init(space, offset, block);
3836
2951
 
3837
2952
        /* The block must be put to the LRU list */
3838
2953
        buf_LRU_add_block(&block->page, FALSE);
3839
2954
 
3840
2955
        buf_block_buf_fix_inc(block, __FILE__, __LINE__);
3841
 
        buf_pool->stat.n_pages_created++;
 
2956
        buf_pool->n_pages_created++;
3842
2957
 
3843
2958
        if (zip_size) {
3844
2959
                void*   data;
3845
2960
                ibool   lru;
3846
2961
 
3847
2962
                /* Prevent race conditions during buf_buddy_alloc(),
3848
 
                which may release and reacquire buf_pool->mutex,
 
2963
                which may release and reacquire buf_pool_mutex,
3849
2964
                by IO-fixing and X-latching the block. */
3850
2965
 
3851
2966
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3853
2968
 
3854
2969
                page_zip_set_size(&block->page.zip, zip_size);
3855
2970
                mutex_exit(&block->mutex);
3856
 
                /* buf_pool->mutex may be released and reacquired by
 
2971
                /* buf_pool_mutex may be released and reacquired by
3857
2972
                buf_buddy_alloc().  Thus, we must release block->mutex
3858
2973
                in order not to break the latching order in
3859
 
                the reacquisition of buf_pool->mutex.  We also must
 
2974
                the reacquisition of buf_pool_mutex.  We also must
3860
2975
                defer this operation until after the block descriptor
3861
2976
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3862
 
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2977
                data = buf_buddy_alloc(zip_size, &lru);
3863
2978
                mutex_enter(&block->mutex);
3864
 
                block->page.zip.data = static_cast<unsigned char *>(data);
 
2979
                block->page.zip.data = data;
3865
2980
 
3866
2981
                /* To maintain the invariant
3867
2982
                block->in_unzip_LRU_list
3875
2990
                rw_lock_x_unlock(&block->lock);
3876
2991
        }
3877
2992
 
3878
 
        buf_page_set_accessed(&block->page, time_ms);
3879
 
 
3880
 
        buf_pool_mutex_exit(buf_pool);
 
2993
        buf_pool_mutex_exit();
3881
2994
 
3882
2995
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3883
2996
 
 
2997
        buf_page_set_accessed(&block->page, TRUE);
 
2998
 
3884
2999
        mutex_exit(&block->mutex);
3885
3000
 
3886
3001
        /* Delete possible entries for the page from the insert buffer:
3889
3004
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3890
3005
 
3891
3006
        /* Flush pages from the end of the LRU list if necessary */
3892
 
        buf_flush_free_margin(buf_pool);
 
3007
        buf_flush_free_margin();
3893
3008
 
3894
3009
        frame = block->frame;
3895
3010
 
3925
3040
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
3926
3041
{
3927
3042
        enum buf_io_fix io_type;
3928
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3929
3043
        const ibool     uncompressed = (buf_page_get_state(bpage)
3930
3044
                                        == BUF_BLOCK_FILE_PAGE);
3931
3045
 
4061
3175
                }
4062
3176
        }
4063
3177
 
4064
 
        buf_pool_mutex_enter(buf_pool);
 
3178
        buf_pool_mutex_enter();
4065
3179
        mutex_enter(buf_page_get_mutex(bpage));
4066
3180
 
4067
3181
#ifdef UNIV_IBUF_COUNT_DEBUG
4087
3201
 
4088
3202
                ut_ad(buf_pool->n_pend_reads > 0);
4089
3203
                buf_pool->n_pend_reads--;
4090
 
                buf_pool->stat.n_pages_read++;
 
3204
                buf_pool->n_pages_read++;
4091
3205
 
4092
3206
                if (uncompressed) {
4093
3207
                        rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock,
4107
3221
                                             BUF_IO_WRITE);
4108
3222
                }
4109
3223
 
4110
 
                buf_pool->stat.n_pages_written++;
 
3224
                buf_pool->n_pages_written++;
4111
3225
 
4112
3226
                break;
4113
3227
 
4125
3239
#endif /* UNIV_DEBUG */
4126
3240
 
4127
3241
        mutex_exit(buf_page_get_mutex(bpage));
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
 
3242
        buf_pool_mutex_exit();
 
3243
}
 
3244
 
 
3245
/*********************************************************************//**
 
3246
Invalidates the file pages in the buffer pool when an archive recovery is
 
3247
completed. All the file pages buffered must be in a replaceable state when
 
3248
this function is called: not latched and not modified. */
 
3249
UNIV_INTERN
4170
3250
void
4171
 
buf_pool_invalidate_instance(
4172
 
/*=========================*/
4173
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3251
buf_pool_invalidate(void)
 
3252
/*=====================*/
4174
3253
{
4175
 
        ibool           freed;
4176
 
        int     i;
4177
 
 
4178
 
        buf_pool_mutex_enter(buf_pool);
4179
 
 
4180
 
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
4181
 
 
4182
 
                /* As this function is called during startup and
4183
 
                during redo application phase during recovery, InnoDB
4184
 
                is single threaded (apart from IO helper threads) at
4185
 
                this stage. No new write batch can be in intialization
4186
 
                stage at this point. */
4187
 
                ut_ad(buf_pool->init_flush[i] == FALSE);
4188
 
 
4189
 
                /* However, it is possible that a write batch that has
4190
 
                been posted earlier is still not complete. For buffer
4191
 
                pool invalidation to proceed we must ensure there is NO
4192
 
                write activity happening. */
4193
 
                if (buf_pool->n_flush[i] > 0) {
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);
4197
 
                }
4198
 
        }
4199
 
 
4200
 
        buf_pool_mutex_exit(buf_pool);
4201
 
 
4202
 
        ut_ad(buf_all_freed_instance(buf_pool));
 
3254
        ibool   freed;
 
3255
 
 
3256
        ut_ad(buf_all_freed());
4203
3257
 
4204
3258
        freed = TRUE;
4205
3259
 
4206
3260
        while (freed) {
4207
 
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
 
3261
                freed = buf_LRU_search_and_free_block(100);
4208
3262
        }
4209
3263
 
4210
 
        buf_pool_mutex_enter(buf_pool);
 
3264
        buf_pool_mutex_enter();
4211
3265
 
4212
3266
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
4213
3267
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
4214
3268
 
4215
 
        buf_pool->freed_page_clock = 0;
4216
 
        buf_pool->LRU_old = NULL;
4217
 
        buf_pool->LRU_old_len = 0;
4218
 
        buf_pool->LRU_flush_ended = 0;
4219
 
 
4220
 
        memset(&buf_pool->stat, 0x00, sizeof(buf_pool->stat));
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
 
        }
 
3269
        buf_pool_mutex_exit();
4240
3270
}
4241
3271
 
4242
3272
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4243
3273
/*********************************************************************//**
4244
 
Validates data in one buffer pool instance
 
3274
Validates the buffer buf_pool data structure.
4245
3275
@return TRUE */
4246
 
static
 
3276
UNIV_INTERN
4247
3277
ibool
4248
 
buf_pool_validate_instance(
4249
 
/*=======================*/
4250
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3278
buf_validate(void)
 
3279
/*==============*/
4251
3280
{
4252
3281
        buf_page_t*     b;
4253
3282
        buf_chunk_t*    chunk;
4262
3291
 
4263
3292
        ut_ad(buf_pool);
4264
3293
 
4265
 
        buf_pool_mutex_enter(buf_pool);
 
3294
        buf_pool_mutex_enter();
4266
3295
 
4267
3296
        chunk = buf_pool->chunks;
4268
3297
 
4287
3316
                                break;
4288
3317
 
4289
3318
                        case BUF_BLOCK_FILE_PAGE:
4290
 
                                ut_a(buf_page_hash_get(buf_pool,
4291
 
                                                       buf_block_get_space(
 
3319
                                ut_a(buf_page_hash_get(buf_block_get_space(
4292
3320
                                                               block),
4293
3321
                                                       buf_block_get_page_no(
4294
3322
                                                               block))
4335
3363
                                }
4336
3364
 
4337
3365
                                n_lru++;
 
3366
 
 
3367
                                if (block->page.oldest_modification > 0) {
 
3368
                                        n_flush++;
 
3369
                                }
 
3370
 
4338
3371
                                break;
4339
3372
 
4340
3373
                        case BUF_BLOCK_NOT_USED:
4352
3385
                }
4353
3386
        }
4354
3387
 
4355
 
        mutex_enter(&buf_pool->zip_mutex);
 
3388
        mutex_enter(&buf_pool_zip_mutex);
4356
3389
 
4357
3390
        /* Check clean compressed-only blocks. */
4358
3391
 
4373
3406
                        ut_error;
4374
3407
                        break;
4375
3408
                }
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. */
4380
3409
                ut_a(!b->oldest_modification);
4381
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3410
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4382
3411
 
4383
3412
                n_lru++;
4384
3413
                n_zip++;
4385
3414
        }
4386
3415
 
4387
 
        /* Check dirty blocks. */
 
3416
        /* Check dirty compressed-only blocks. */
4388
3417
 
4389
 
        buf_flush_list_mutex_enter(buf_pool);
4390
3418
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4391
3419
             b = UT_LIST_GET_NEXT(list, b)) {
4392
3420
                ut_ad(b->in_flush_list);
4393
 
                ut_a(b->oldest_modification);
4394
 
                n_flush++;
4395
3421
 
4396
3422
                switch (buf_page_get_state(b)) {
4397
3423
                case BUF_BLOCK_ZIP_DIRTY:
 
3424
                        ut_a(b->oldest_modification);
4398
3425
                        n_lru++;
 
3426
                        n_flush++;
4399
3427
                        n_zip++;
4400
3428
                        switch (buf_page_get_io_fix(b)) {
4401
3429
                        case BUF_IO_NONE:
4402
3430
                        case BUF_IO_READ:
4403
3431
                                break;
 
3432
 
4404
3433
                        case BUF_IO_WRITE:
4405
3434
                                switch (buf_page_get_flush_type(b)) {
4406
3435
                                case BUF_FLUSH_LRU:
4430
3459
                        ut_error;
4431
3460
                        break;
4432
3461
                }
4433
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3462
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4434
3463
        }
4435
3464
 
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);
 
3465
        mutex_exit(&buf_pool_zip_mutex);
4441
3466
 
4442
3467
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
4443
3468
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
4453
3478
                        (ulong) n_free);
4454
3479
                ut_error;
4455
3480
        }
 
3481
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4456
3482
 
4457
3483
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
4458
3484
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
4459
3485
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
4460
3486
 
4461
 
        buf_pool_mutex_exit(buf_pool);
 
3487
        buf_pool_mutex_exit();
4462
3488
 
4463
3489
        ut_a(buf_LRU_validate());
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
 
 
 
3490
        ut_a(buf_flush_validate());
 
3491
 
 
3492
        return(TRUE);
 
3493
}
4489
3494
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
4490
3495
 
4491
3496
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4492
3497
/*********************************************************************//**
4493
 
Prints info of the buffer buf_pool data structure for one instance. */
4494
 
static
 
3498
Prints info of the buffer buf_pool data structure. */
 
3499
UNIV_INTERN
4495
3500
void
4496
 
buf_print_instance(
4497
 
/*===============*/
4498
 
        buf_pool_t*     buf_pool)
 
3501
buf_print(void)
 
3502
/*===========*/
4499
3503
{
4500
 
        index_id_t*     index_ids;
 
3504
        dulint*         index_ids;
4501
3505
        ulint*          counts;
4502
3506
        ulint           size;
4503
3507
        ulint           i;
4504
3508
        ulint           j;
4505
 
        index_id_t      id;
 
3509
        dulint          id;
4506
3510
        ulint           n_found;
4507
3511
        buf_chunk_t*    chunk;
4508
3512
        dict_index_t*   index;
4511
3515
 
4512
3516
        size = buf_pool->curr_size;
4513
3517
 
4514
 
        index_ids = mem_alloc(size * sizeof *index_ids);
 
3518
        index_ids = mem_alloc(sizeof(dulint) * size);
4515
3519
        counts = mem_alloc(sizeof(ulint) * size);
4516
3520
 
4517
 
        buf_pool_mutex_enter(buf_pool);
4518
 
        buf_flush_list_mutex_enter(buf_pool);
 
3521
        buf_pool_mutex_enter();
4519
3522
 
4520
3523
        fprintf(stderr,
4521
3524
                "buf_pool size %lu\n"
4525
3528
                "n pending decompressions %lu\n"
4526
3529
                "n pending reads %lu\n"
4527
3530
                "n pending flush LRU %lu list %lu single page %lu\n"
4528
 
                "pages made young %lu, not young %lu\n"
4529
3531
                "pages read %lu, created %lu, written %lu\n",
4530
3532
                (ulong) size,
4531
3533
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4536
3538
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU],
4537
3539
                (ulong) buf_pool->n_flush[BUF_FLUSH_LIST],
4538
3540
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE],
4539
 
                (ulong) buf_pool->stat.n_pages_made_young,
4540
 
                (ulong) buf_pool->stat.n_pages_not_made_young,
4541
 
                (ulong) buf_pool->stat.n_pages_read,
4542
 
                (ulong) buf_pool->stat.n_pages_created,
4543
 
                (ulong) buf_pool->stat.n_pages_written);
4544
 
 
4545
 
        buf_flush_list_mutex_exit(buf_pool);
 
3541
                (ulong) buf_pool->n_pages_read, buf_pool->n_pages_created,
 
3542
                (ulong) buf_pool->n_pages_written);
4546
3543
 
4547
3544
        /* Count the number of blocks belonging to each index in the buffer */
4548
3545
 
4566
3563
 
4567
3564
                                while (j < n_found) {
4568
3565
 
4569
 
                                        if (index_ids[j] == id) {
 
3566
                                        if (ut_dulint_cmp(index_ids[j],
 
3567
                                                          id) == 0) {
4570
3568
                                                counts[j]++;
4571
3569
 
4572
3570
                                                break;
4583
3581
                }
4584
3582
        }
4585
3583
 
4586
 
        buf_pool_mutex_exit(buf_pool);
 
3584
        buf_pool_mutex_exit();
4587
3585
 
4588
3586
        for (i = 0; i < n_found; i++) {
4589
3587
                index = dict_index_get_if_in_cache(index_ids[i]);
4590
3588
 
4591
3589
                fprintf(stderr,
4592
 
                        "Block count for index %llu in buffer is about %lu",
4593
 
                        (ullint) index_ids[i],
 
3590
                        "Block count for index %lu in buffer is about %lu",
 
3591
                        (ulong) ut_dulint_get_low(index_ids[i]),
4594
3592
                        (ulong) counts[i]);
4595
3593
 
4596
3594
                if (index) {
4604
3602
        mem_free(index_ids);
4605
3603
        mem_free(counts);
4606
3604
 
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
 
        }
 
3605
        ut_a(buf_validate());
4625
3606
}
4626
3607
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
4627
3608
 
4631
3612
@return number of latched pages */
4632
3613
UNIV_INTERN
4633
3614
ulint
4634
 
buf_get_latched_pages_number_instance(
4635
 
/*==================================*/
4636
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3615
buf_get_latched_pages_number(void)
 
3616
/*==============================*/
4637
3617
{
 
3618
        buf_chunk_t*    chunk;
4638
3619
        buf_page_t*     b;
4639
3620
        ulint           i;
4640
 
        buf_chunk_t*    chunk;
4641
3621
        ulint           fixed_pages_number = 0;
4642
3622
 
4643
 
        buf_pool_mutex_enter(buf_pool);
 
3623
        buf_pool_mutex_enter();
4644
3624
 
4645
3625
        chunk = buf_pool->chunks;
4646
3626
 
4669
3649
                }
4670
3650
        }
4671
3651
 
4672
 
        mutex_enter(&buf_pool->zip_mutex);
 
3652
        mutex_enter(&buf_pool_zip_mutex);
4673
3653
 
4674
3654
        /* Traverse the lists of clean and dirty compressed-only blocks. */
4675
3655
 
4684
3664
                }
4685
3665
        }
4686
3666
 
4687
 
        buf_flush_list_mutex_enter(buf_pool);
4688
3667
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4689
3668
             b = UT_LIST_GET_NEXT(list, b)) {
4690
3669
                ut_ad(b->in_flush_list);
4710
3689
                }
4711
3690
        }
4712
3691
 
4713
 
        buf_flush_list_mutex_exit(buf_pool);
4714
 
        mutex_exit(&buf_pool->zip_mutex);
4715
 
        buf_pool_mutex_exit(buf_pool);
 
3692
        mutex_exit(&buf_pool_zip_mutex);
 
3693
        buf_pool_mutex_exit();
4716
3694
 
4717
3695
        return(fixed_pages_number);
4718
3696
}
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
 
 
4743
3697
#endif /* UNIV_DEBUG */
4744
3698
 
4745
3699
/*********************************************************************//**
4750
3704
buf_get_n_pending_ios(void)
4751
3705
/*=======================*/
4752
3706
{
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);
 
3707
        return(buf_pool->n_pend_reads
 
3708
               + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3709
               + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3710
               + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4769
3711
}
4770
3712
 
4771
3713
/*********************************************************************//**
4777
3719
buf_get_modified_ratio_pct(void)
4778
3720
/*============================*/
4779
3721
{
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
 
  
 
3722
        ulint   ratio;
 
3723
 
 
3724
        buf_pool_mutex_enter();
 
3725
 
 
3726
        ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
 
3727
                / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
 
3728
                   + UT_LIST_GET_LEN(buf_pool->free));
 
3729
 
4789
3730
        /* 1 + is there to avoid division by zero */
4790
3731
 
 
3732
        buf_pool_mutex_exit();
 
3733
 
4791
3734
        return(ratio);
4792
3735
}
4793
3736
 
4794
3737
/*********************************************************************//**
4795
3738
Prints info of the buffer i/o. */
4796
 
static
 
3739
UNIV_INTERN
4797
3740
void
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 */
 
3741
buf_print_io(
 
3742
/*=========*/
 
3743
        FILE*   file)   /*!< in/out: buffer where to print */
4802
3744
{
4803
3745
        time_t  current_time;
4804
3746
        double  time_elapsed;
4805
 
        ulint   n_gets_diff;
 
3747
        ulint   size;
4806
3748
 
4807
3749
        ut_ad(buf_pool);
 
3750
        size = buf_pool->curr_size;
4808
3751
 
4809
 
        buf_pool_mutex_enter(buf_pool);
4810
 
        buf_flush_list_mutex_enter(buf_pool);
 
3752
        buf_pool_mutex_enter();
4811
3753
 
4812
3754
        fprintf(file,
4813
3755
                "Buffer pool size   %lu\n"
4814
3756
                "Free buffers       %lu\n"
4815
3757
                "Database pages     %lu\n"
4816
 
                "Old database pages %lu\n"
4817
3758
                "Modified db pages  %lu\n"
4818
3759
                "Pending reads %lu\n"
4819
3760
                "Pending writes: LRU %lu, flush list %lu, single page %lu\n",
4820
 
                (ulong) buf_pool->curr_size,
 
3761
                (ulong) size,
4821
3762
                (ulong) UT_LIST_GET_LEN(buf_pool->free),
4822
3763
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4823
 
                (ulong) buf_pool->LRU_old_len,
4824
3764
                (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
4825
3765
                (ulong) buf_pool->n_pend_reads,
4826
3766
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
4829
3769
                + buf_pool->init_flush[BUF_FLUSH_LIST],
4830
3770
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4831
3771
 
4832
 
        buf_flush_list_mutex_exit(buf_pool);
4833
 
 
4834
3772
        current_time = time(NULL);
4835
3773
        time_elapsed = 0.001 + difftime(current_time,
4836
3774
                                        buf_pool->last_printout_time);
 
3775
        buf_pool->last_printout_time = current_time;
4837
3776
 
4838
3777
        fprintf(file,
4839
 
                "Pages made young %lu, not young %lu\n"
4840
 
                "%.2f youngs/s, %.2f non-youngs/s\n"
4841
3778
                "Pages read %lu, created %lu, written %lu\n"
4842
3779
                "%.2f reads/s, %.2f creates/s, %.2f writes/s\n",
4843
 
                (ulong) buf_pool->stat.n_pages_made_young,
4844
 
                (ulong) buf_pool->stat.n_pages_not_made_young,
4845
 
                (buf_pool->stat.n_pages_made_young
4846
 
                 - buf_pool->old_stat.n_pages_made_young)
4847
 
                / time_elapsed,
4848
 
                (buf_pool->stat.n_pages_not_made_young
4849
 
                 - buf_pool->old_stat.n_pages_not_made_young)
4850
 
                / time_elapsed,
4851
 
                (ulong) buf_pool->stat.n_pages_read,
4852
 
                (ulong) buf_pool->stat.n_pages_created,
4853
 
                (ulong) buf_pool->stat.n_pages_written,
4854
 
                (buf_pool->stat.n_pages_read
4855
 
                 - buf_pool->old_stat.n_pages_read)
4856
 
                / time_elapsed,
4857
 
                (buf_pool->stat.n_pages_created
4858
 
                 - buf_pool->old_stat.n_pages_created)
4859
 
                / time_elapsed,
4860
 
                (buf_pool->stat.n_pages_written
4861
 
                 - buf_pool->old_stat.n_pages_written)
 
3780
                (ulong) buf_pool->n_pages_read,
 
3781
                (ulong) buf_pool->n_pages_created,
 
3782
                (ulong) buf_pool->n_pages_written,
 
3783
                (buf_pool->n_pages_read - buf_pool->n_pages_read_old)
 
3784
                / time_elapsed,
 
3785
                (buf_pool->n_pages_created - buf_pool->n_pages_created_old)
 
3786
                / time_elapsed,
 
3787
                (buf_pool->n_pages_written - buf_pool->n_pages_written_old)
4862
3788
                / time_elapsed);
4863
3789
 
4864
 
        n_gets_diff = buf_pool->stat.n_page_gets
4865
 
                    - buf_pool->old_stat.n_page_gets;
4866
 
 
4867
 
        if (n_gets_diff) {
4868
 
                fprintf(file,
4869
 
                        "Buffer pool hit rate %lu / 1000,"
4870
 
                        " young-making rate %lu / 1000 not %lu / 1000\n",
4871
 
                        (ulong)
4872
 
                        (1000 - ((1000 * (buf_pool->stat.n_pages_read
4873
 
                                          - buf_pool->old_stat.n_pages_read))
4874
 
                                 / (buf_pool->stat.n_page_gets
4875
 
                                    - buf_pool->old_stat.n_page_gets))),
4876
 
                        (ulong)
4877
 
                        (1000 * (buf_pool->stat.n_pages_made_young
4878
 
                                 - buf_pool->old_stat.n_pages_made_young)
4879
 
                         / n_gets_diff),
4880
 
                        (ulong)
4881
 
                        (1000 * (buf_pool->stat.n_pages_not_made_young
4882
 
                                 - buf_pool->old_stat.n_pages_not_made_young)
4883
 
                         / n_gets_diff));
 
3790
        if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
 
3791
                fprintf(file, "Buffer pool hit rate %lu / 1000\n",
 
3792
                        (ulong)
 
3793
                        (1000 - ((1000 * (buf_pool->n_pages_read
 
3794
                                          - buf_pool->n_pages_read_old))
 
3795
                                 / (buf_pool->n_page_gets
 
3796
                                    - buf_pool->n_page_gets_old))));
4884
3797
        } else {
4885
3798
                fputs("No buffer pool page gets since the last printout\n",
4886
3799
                      file);
4887
3800
        }
4888
3801
 
4889
 
        /* Statistics about read ahead algorithm */
4890
 
        fprintf(file, "Pages read ahead %.2f/s,"
4891
 
                " evicted without access %.2f/s\n",
4892
 
                (buf_pool->stat.n_ra_pages_read
4893
 
                - buf_pool->old_stat.n_ra_pages_read)
4894
 
                / time_elapsed,
4895
 
                (buf_pool->stat.n_ra_pages_evicted
4896
 
                - buf_pool->old_stat.n_ra_pages_evicted)
4897
 
                / time_elapsed);
 
3802
        buf_pool->n_page_gets_old = buf_pool->n_page_gets;
 
3803
        buf_pool->n_pages_read_old = buf_pool->n_pages_read;
 
3804
        buf_pool->n_pages_created_old = buf_pool->n_pages_created;
 
3805
        buf_pool->n_pages_written_old = buf_pool->n_pages_written;
4898
3806
 
4899
3807
        /* Print some values to help us with visualizing what is
4900
3808
        happening with LRU eviction. */
4901
3809
        fprintf(file,
4902
3810
                "LRU len: %lu, unzip_LRU len: %lu\n"
4903
3811
                "I/O sum[%lu]:cur[%lu], unzip sum[%lu]:cur[%lu]\n",
4904
 
                static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->LRU)),
4905
 
                static_cast<ulint>(UT_LIST_GET_LEN(buf_pool->unzip_LRU)),
 
3812
                UT_LIST_GET_LEN(buf_pool->LRU),
 
3813
                UT_LIST_GET_LEN(buf_pool->unzip_LRU),
4906
3814
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
4907
3815
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
4908
3816
 
4909
 
        buf_refresh_io_stats(buf_pool);
4910
 
        buf_pool_mutex_exit(buf_pool);
 
3817
        buf_pool_mutex_exit();
 
3818
}
 
3819
 
 
3820
/**********************************************************************//**
 
3821
Refreshes the statistics used to print per-second averages. */
 
3822
UNIV_INTERN
 
3823
void
 
3824
buf_refresh_io_stats(void)
 
3825
/*======================*/
 
3826
{
 
3827
        buf_pool->last_printout_time = time(NULL);
 
3828
        buf_pool->n_page_gets_old = buf_pool->n_page_gets;
 
3829
        buf_pool->n_pages_read_old = buf_pool->n_pages_read;
 
3830
        buf_pool->n_pages_created_old = buf_pool->n_pages_created;
 
3831
        buf_pool->n_pages_written_old = buf_pool->n_pages_written;
4911
3832
}
4912
3833
 
4913
3834
/*********************************************************************//**
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
 
        }
4929
 
}
4930
 
 
4931
 
/**********************************************************************//**
4932
 
Refreshes the statistics used to print per-second averages. */
4933
 
UNIV_INTERN
4934
 
void
4935
 
buf_refresh_io_stats(
4936
 
/*=================*/
4937
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
4938
 
{
4939
 
        buf_pool->last_printout_time = ut_time();
4940
 
        buf_pool->old_stat = buf_pool->stat;
4941
 
}
4942
 
 
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 */
 
3835
Asserts that all file pages in the buffer are in a replaceable state.
 
3836
@return TRUE */
4964
3837
UNIV_INTERN
4965
3838
ibool
4966
3839
buf_all_freed(void)
4967
3840
/*===============*/
4968
3841
{
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);
 
3842
        buf_chunk_t*    chunk;
 
3843
        ulint           i;
 
3844
 
 
3845
        ut_ad(buf_pool);
 
3846
 
 
3847
        buf_pool_mutex_enter();
 
3848
 
 
3849
        chunk = buf_pool->chunks;
 
3850
 
 
3851
        for (i = buf_pool->n_chunks; i--; chunk++) {
 
3852
 
 
3853
                const buf_block_t* block = buf_chunk_not_freed(chunk);
 
3854
 
 
3855
                if (UNIV_LIKELY_NULL(block)) {
 
3856
                        fprintf(stderr,
 
3857
                                "Page %lu %lu still fixed or dirty\n",
 
3858
                                (ulong) block->page.space,
 
3859
                                (ulong) block->page.offset);
 
3860
                        ut_error;
4978
3861
                }
4979
 
        }
 
3862
        }
 
3863
 
 
3864
        buf_pool_mutex_exit();
4980
3865
 
4981
3866
        return(TRUE);
4982
3867
}
4983
 
  
 
3868
 
4984
3869
/*********************************************************************//**
4985
3870
Checks that there currently are no pending i/o-operations for the buffer
4986
3871
pool.
4990
3875
buf_pool_check_no_pending_io(void)
4991
3876
/*==============================*/
4992
3877
{
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
 
                }
 
3878
        ibool   ret;
 
3879
 
 
3880
        buf_pool_mutex_enter();
 
3881
 
 
3882
        if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3883
            + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3884
            + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
 
3885
                ret = FALSE;
 
3886
        } else {
 
3887
                ret = TRUE;
5010
3888
        }
5011
3889
 
5012
 
        buf_pool_mutex_exit_all();
 
3890
        buf_pool_mutex_exit();
5013
3891
 
5014
3892
        return(ret);
5015
3893
}
5016
3894
 
5017
 
#if 0
5018
 
Code currently not used
5019
3895
/*********************************************************************//**
5020
3896
Gets the current length of the free list of buffer blocks.
5021
3897
@return length of the free list */
5026
3902
{
5027
3903
        ulint   len;
5028
3904
 
5029
 
        buf_pool_mutex_enter(buf_pool);
 
3905
        buf_pool_mutex_enter();
5030
3906
 
5031
3907
        len = UT_LIST_GET_LEN(buf_pool->free);
5032
3908
 
5033
 
        buf_pool_mutex_exit(buf_pool);
 
3909
        buf_pool_mutex_exit();
5034
3910
 
5035
3911
        return(len);
5036
3912
}
5037
 
#endif
5038
 
 
5039
3913
#else /* !UNIV_HOTBACKUP */
5040
3914
/********************************************************************//**
5041
3915
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */