~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Jay Pipes
  • Date: 2008-12-18 15:55:03 UTC
  • mto: This revision was merged to the branch mainline in revision 717.
  • Revision ID: jpipes@serialcoder-20081218155503-u45ygyunrdyyvquq
Fix for Bug#308457.  Gave UTF8 enclosure and escape character on LOAD DATA INFILE and changed the error message to be more descriptive

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*****************************************************************************
2
 
 
3
 
Copyright (C) 1995, 2010, Innobase Oy. All Rights Reserved.
4
 
Copyright (C) 2008, Google Inc.
5
 
 
6
 
Portions of this file contain modifications contributed and copyrighted by
7
 
Google, Inc. Those modifications are gratefully acknowledged and are described
8
 
briefly in the InnoDB documentation. The contributions by Google are
9
 
incorporated with their permission, and subject to the conditions contained in
10
 
the file COPYING.Google.
11
 
 
12
 
This program is free software; you can redistribute it and/or modify it under
13
 
the terms of the GNU General Public License as published by the Free Software
14
 
Foundation; version 2 of the License.
15
 
 
16
 
This program is distributed in the hope that it will be useful, but WITHOUT
17
 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
 
 
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
23
 
 
24
 
*****************************************************************************/
25
 
 
26
 
/**************************************************//**
27
 
@file buf/buf0buf.c
 
1
/*   Innobase relational database engine; Copyright (C) 2001 Innobase Oy
 
2
 
 
3
     This program is free software; you can redistribute it and/or modify
 
4
     it under the terms of the GNU General Public License 2
 
5
     as published by the Free Software Foundation in June 1991.
 
6
 
 
7
     This program is distributed in the hope that it will be useful,
 
8
     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
     GNU General Public License for more details.
 
11
 
 
12
     You should have received a copy of the GNU General Public License 2
 
13
     along with this program (in file COPYING); if not, write to the Free
 
14
     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
15
/******************************************************
28
16
The database buffer buf_pool
29
17
 
 
18
(c) 1995 Innobase Oy
 
19
 
30
20
Created 11/5/1995 Heikki Tuuri
31
21
*******************************************************/
32
22
 
36
26
#include "buf0buf.ic"
37
27
#endif
38
28
 
 
29
#include "buf0buddy.h"
39
30
#include "mem0mem.h"
40
31
#include "btr0btr.h"
41
32
#include "fil0fil.h"
42
 
#ifndef UNIV_HOTBACKUP
43
 
#include "buf0buddy.h"
44
33
#include "lock0lock.h"
45
34
#include "btr0sea.h"
46
35
#include "ibuf0ibuf.h"
 
36
#include "dict0dict.h"
 
37
#include "log0recv.h"
 
38
#include "log0log.h"
47
39
#include "trx0undo.h"
48
 
#include "log0log.h"
49
 
#endif /* !UNIV_HOTBACKUP */
50
40
#include "srv0srv.h"
51
 
#include "dict0dict.h"
52
 
#include "log0recv.h"
53
41
#include "page0zip.h"
54
42
 
55
 
#include <drizzled/errmsg_print.h>
56
 
 
57
43
/*
58
44
                IMPLEMENTATION OF THE BUFFER POOL
59
45
                =================================
86
72
The buffer buf_pool contains a single mutex which protects all the
87
73
control data structures of the buf_pool. The content of a buffer frame is
88
74
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.
 
75
These locks can be locked and unlocked without owning the buf_pool mutex.
90
76
The OS events in the buf_pool struct can be waited for without owning the
91
 
buf_pool->mutex.
 
77
buf_pool mutex.
92
78
 
93
 
The buf_pool->mutex is a hot-spot in main memory, causing a lot of
 
79
The buf_pool mutex is a hot-spot in main memory, causing a lot of
94
80
memory bus traffic on multiprocessor systems when processors
95
81
alternately access the mutex. On our Pentium, the mutex is accessed
96
82
maybe every 10 microseconds. We gave up the solution to have mutexes
97
83
for each control block, for instance, because it seemed to be
98
84
complicated.
99
85
 
100
 
A solution to reduce mutex contention of the buf_pool->mutex is to
 
86
A solution to reduce mutex contention of the buf_pool mutex is to
101
87
create a separate mutex for the page hash table. On Pentium,
102
88
accessing the hash table takes 2 microseconds, about half
103
 
of the total buf_pool->mutex hold time.
 
89
of the total buf_pool mutex hold time.
104
90
 
105
91
                Control blocks
106
92
                --------------
155
141
which we can use when we want to artificially age a page in the
156
142
buf_pool. This is used if we know that some page is not needed
157
143
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.
 
144
causing it to be replaced sooner than would noramlly be the case.
159
145
Currently this aging mechanism is used for read-ahead mechanism
160
146
of pages, and it can also be used when there is a scan of a full
161
147
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.
 
148
of the LRU list, we make sure that most of the buf_pool stays in the
 
149
main memory, undisturbed.
164
150
 
165
151
The unzip_LRU list contains a subset of the common LRU list.  The
166
152
blocks on the unzip_LRU list hold a compressed file page and the
174
160
holding file pages that have been modified in the memory
175
161
but not written to disk yet. The block with the oldest modification
176
162
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
163
 
179
164
The chain of unmodified compressed blocks (buf_pool->zip_clean)
180
165
contains the control blocks (buf_page_t) of those compressed pages
242
227
the read requests for the whole area.
243
228
*/
244
229
 
245
 
#ifndef UNIV_HOTBACKUP
246
 
/** Value in microseconds */
 
230
/* Value in microseconds */
247
231
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;
 
232
 
 
233
/* The buffer buf_pool of the database */
 
234
UNIV_INTERN buf_pool_t* buf_pool = NULL;
 
235
 
 
236
/* mutex protecting the buffer pool struct and control blocks, except the
 
237
read-write lock in them */
 
238
UNIV_INTERN mutex_t             buf_pool_mutex;
 
239
/* mutex protecting the control blocks of compressed-only pages
 
240
(of type buf_page_t, not buf_block_t) */
 
241
UNIV_INTERN mutex_t             buf_pool_zip_mutex;
253
242
 
254
243
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
255
 
static ulint    buf_dbg_counter = 0; /*!< This is used to insert validation
256
 
                                        operations in execution in the
 
244
static ulint    buf_dbg_counter = 0; /* This is used to insert validation
 
245
                                        operations in excution in the
257
246
                                        debug version */
 
247
/** Flag to forbid the release of the buffer pool mutex.
 
248
Protected by buf_pool->mutex. */
 
249
UNIV_INTERN ulint               buf_pool_mutex_exit_forbidden = 0;
258
250
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
259
251
#ifdef UNIV_DEBUG
260
 
/** If this is set TRUE, the program prints info whenever
 
252
/* If this is set TRUE, the program prints info whenever
261
253
read-ahead or flush occurs */
262
254
UNIV_INTERN ibool               buf_debug_prints = FALSE;
263
255
#endif /* UNIV_DEBUG */
264
256
 
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
 
/** A chunk of buffers.  The buffer pool is allocated in chunks. */
 
257
/* A chunk of buffers.  The buffer pool is allocated in chunks. */
300
258
struct buf_chunk_struct{
301
 
        ulint           mem_size;       /*!< allocated size of the chunk */
302
 
        ulint           size;           /*!< size of frames[] and blocks[] */
303
 
        void*           mem;            /*!< pointer to the memory area which
 
259
        ulint           mem_size;       /* allocated size of the chunk */
 
260
        ulint           size;           /* size of frames[] and blocks[] */
 
261
        void*           mem;            /* pointer to the memory area which
304
262
                                        was allocated for the frames */
305
 
        buf_block_t*    blocks;         /*!< array of buffer control blocks */
 
263
        buf_block_t*    blocks;         /* array of buffer control blocks */
306
264
};
307
 
#endif /* !UNIV_HOTBACKUP */
308
 
 
309
 
/********************************************************************//**
310
 
Gets the smallest oldest_modification lsn for any page in the pool. Returns
311
 
zero if all modified pages have been flushed to disk.
312
 
@return oldest modification in pool, zero if none */
313
 
UNIV_INTERN
314
 
ib_uint64_t
315
 
buf_pool_get_oldest_modification(void)
316
 
/*==================================*/
317
 
{
318
 
        ulint           i;
319
 
        buf_page_t*     bpage;
320
 
        ib_uint64_t     lsn = 0;
321
 
        ib_uint64_t     oldest_lsn = 0;
322
 
 
323
 
        /* When we traverse all the flush lists we don't want another
324
 
        thread to add a dirty page to any flush list. */
325
 
        log_flush_order_mutex_enter();
326
 
 
327
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
328
 
                buf_pool_t*     buf_pool;
329
 
 
330
 
                buf_pool = buf_pool_from_array(i);
331
 
 
332
 
                buf_flush_list_mutex_enter(buf_pool);
333
 
 
334
 
                bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
335
 
 
336
 
                if (bpage != NULL) {
337
 
                        ut_ad(bpage->in_flush_list);
338
 
                        lsn = bpage->oldest_modification;
339
 
                }
340
 
 
341
 
                buf_flush_list_mutex_exit(buf_pool);
342
 
 
343
 
                if (!oldest_lsn || oldest_lsn > lsn) {
344
 
                        oldest_lsn = lsn;
345
 
                }
346
 
        }
347
 
 
348
 
        log_flush_order_mutex_exit();
349
 
 
350
 
        /* The returned answer may be out of date: the flush_list can
351
 
        change after the mutex has been released. */
352
 
 
353
 
        return(oldest_lsn);
354
 
}
355
 
 
356
 
/********************************************************************//**
357
 
Get total buffer pool statistics. */
358
 
UNIV_INTERN
359
 
void
360
 
buf_get_total_list_len(
361
 
/*===================*/
362
 
        ulint*          LRU_len,        /*!< out: length of all LRU lists */
363
 
        ulint*          free_len,       /*!< out: length of all free lists */
364
 
        ulint*          flush_list_len) /*!< out: length of all flush lists */
365
 
{
366
 
        ulint           i;
367
 
 
368
 
        *LRU_len = 0;
369
 
        *free_len = 0;
370
 
        *flush_list_len = 0;
371
 
 
372
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
373
 
                buf_pool_t*     buf_pool;
374
 
 
375
 
                buf_pool = buf_pool_from_array(i);
376
 
                *LRU_len += UT_LIST_GET_LEN(buf_pool->LRU);
377
 
                *free_len += UT_LIST_GET_LEN(buf_pool->free);
378
 
                *flush_list_len += UT_LIST_GET_LEN(buf_pool->flush_list);
379
 
        }
380
 
}
381
 
 
382
 
/********************************************************************//**
383
 
Get total buffer pool statistics. */
384
 
UNIV_INTERN
385
 
void
386
 
buf_get_total_stat(
387
 
/*===============*/
388
 
        buf_pool_stat_t*        tot_stat)       /*!< out: buffer pool stats */
389
 
{
390
 
        ulint                   i;
391
 
 
392
 
        memset(tot_stat, 0, sizeof(*tot_stat));
393
 
 
394
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
395
 
                buf_pool_stat_t*buf_stat;
396
 
                buf_pool_t*     buf_pool;
397
 
 
398
 
                buf_pool = buf_pool_from_array(i);
399
 
 
400
 
                buf_stat = &buf_pool->stat;
401
 
                tot_stat->n_page_gets += buf_stat->n_page_gets;
402
 
                tot_stat->n_pages_read += buf_stat->n_pages_read;
403
 
                tot_stat->n_pages_written += buf_stat->n_pages_written;
404
 
                tot_stat->n_pages_created += buf_stat->n_pages_created;
405
 
                tot_stat->n_ra_pages_read += buf_stat->n_ra_pages_read;
406
 
                tot_stat->n_ra_pages_evicted += buf_stat->n_ra_pages_evicted;
407
 
                tot_stat->n_pages_made_young += buf_stat->n_pages_made_young;
408
 
 
409
 
                tot_stat->n_pages_not_made_young +=
410
 
                        buf_stat->n_pages_not_made_young;
411
 
        }
412
 
}
413
 
 
414
 
/********************************************************************//**
415
 
Allocates a buffer block.
416
 
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
417
 
UNIV_INTERN
418
 
buf_block_t*
419
 
buf_block_alloc(
420
 
/*============*/
421
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
422
 
        ulint           zip_size)       /*!< in: compressed page size in bytes,
423
 
                                        or 0 if uncompressed tablespace */
424
 
{
425
 
        buf_block_t*    block;
426
 
        ulint           index;
427
 
        static ulint    buf_pool_index;
428
 
 
429
 
        if (buf_pool == NULL) {
430
 
                /* We are allocating memory from any buffer pool, ensure
431
 
                we spread the grace on all buffer pool instances. */
432
 
                index = buf_pool_index++ % srv_buf_pool_instances;
433
 
                buf_pool = buf_pool_from_array(index);
434
 
        }
435
 
 
436
 
        block = buf_LRU_get_free_block(buf_pool, zip_size);
437
 
 
438
 
        buf_block_set_state(block, BUF_BLOCK_MEMORY);
439
 
 
440
 
        return(block);
441
 
}
442
 
 
443
 
/********************************************************************//**
 
265
 
 
266
/************************************************************************
444
267
Calculates a page checksum which is stored to the page when it is written
445
268
to a file. Note that we must be careful to calculate the same value on
446
 
32-bit and 64-bit architectures.
447
 
@return checksum */
 
269
32-bit and 64-bit architectures. */
448
270
UNIV_INTERN
449
271
ulint
450
272
buf_calc_page_new_checksum(
451
273
/*=======================*/
452
 
        const byte*     page)   /*!< in: buffer page */
 
274
                                /* out: checksum */
 
275
        const byte*     page)   /* in: buffer page */
453
276
{
454
277
        ulint checksum;
455
278
 
471
294
        return(checksum);
472
295
}
473
296
 
474
 
/********************************************************************//**
 
297
/************************************************************************
475
298
In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
476
299
looked at the first few bytes of the page. This calculates that old
477
300
checksum.
478
301
NOTE: we must first store the new formula checksum to
479
302
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
480
 
because this takes that field as an input!
481
 
@return checksum */
 
303
because this takes that field as an input! */
482
304
UNIV_INTERN
483
305
ulint
484
306
buf_calc_page_old_checksum(
485
307
/*=======================*/
486
 
        const byte*     page)   /*!< in: buffer page */
 
308
                                /* out: checksum */
 
309
        const byte*     page)   /* in: buffer page */
487
310
{
488
311
        ulint checksum;
489
312
 
494
317
        return(checksum);
495
318
}
496
319
 
497
 
/********************************************************************//**
498
 
Checks if a page is corrupt.
499
 
@return TRUE if corrupted */
 
320
/************************************************************************
 
321
Checks if a page is corrupt. */
500
322
UNIV_INTERN
501
323
ibool
502
324
buf_page_is_corrupted(
503
325
/*==================*/
504
 
        const byte*     read_buf,       /*!< in: a database page */
505
 
        ulint           zip_size)       /*!< in: size of compressed page;
 
326
                                        /* out: TRUE if corrupted */
 
327
        const byte*     read_buf,       /* in: a database page */
 
328
        ulint           zip_size)       /* in: size of compressed page;
506
329
                                        0 for uncompressed pages */
507
330
{
508
331
        ulint           checksum_field;
509
332
        ulint           old_checksum_field;
510
 
 
 
333
#ifndef UNIV_HOTBACKUP
 
334
        ib_uint64_t     current_lsn;
 
335
#endif
511
336
        if (UNIV_LIKELY(!zip_size)
512
337
            && memcmp(read_buf + FIL_PAGE_LSN + 4,
513
338
                      read_buf + UNIV_PAGE_SIZE
520
345
        }
521
346
 
522
347
#ifndef UNIV_HOTBACKUP
523
 
        if (recv_lsn_checks_on) {
524
 
                ib_uint64_t     current_lsn;
525
 
 
526
 
                if (log_peek_lsn(&current_lsn)
527
 
                    && UNIV_UNLIKELY
528
 
                    (current_lsn
529
 
                     < mach_read_from_8(read_buf + FIL_PAGE_LSN))) {
 
348
        if (recv_lsn_checks_on && log_peek_lsn(&current_lsn)) {
 
349
                if (current_lsn < mach_read_ull(read_buf + FIL_PAGE_LSN)) {
530
350
                        ut_print_timestamp(stderr);
531
351
 
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);
 
352
                        fprintf(stderr,
 
353
                                "  InnoDB: Error: page %lu log sequence number"
 
354
                                " %"PRIu64"\n"
 
355
                                "InnoDB: is in the future! Current system "
 
356
                                "log sequence number %"PRIu64".\n"
 
357
                                "InnoDB: Your database may be corrupt or "
 
358
                                "you may have copied the InnoDB\n"
 
359
                                "InnoDB: tablespace but not the InnoDB "
 
360
                                "log files. See\n"
 
361
                                "InnoDB: http://dev.mysql.com/doc/refman/"
 
362
                                "5.1/en/forcing-recovery.html\n"
 
363
                                "InnoDB: for more information.\n",
 
364
                                (ulong) mach_read_from_4(read_buf
 
365
                                                         + FIL_PAGE_OFFSET),
 
366
                                mach_read_ull(read_buf + FIL_PAGE_LSN),
 
367
                                current_lsn);
541
368
                }
542
369
        }
543
370
#endif
593
420
        return(FALSE);
594
421
}
595
422
 
596
 
/********************************************************************//**
 
423
/************************************************************************
597
424
Prints a page to stderr. */
598
425
UNIV_INTERN
599
426
void
600
427
buf_page_print(
601
428
/*===========*/
602
 
        const byte*     read_buf,       /*!< in: a database page */
603
 
        ulint           zip_size)       /*!< in: compressed page size, or
 
429
        const byte*     read_buf,       /* in: a database page */
 
430
        ulint           zip_size)       /* in: compressed page size, or
604
431
                                0 for uncompressed pages */
605
432
{
606
 
#ifndef UNIV_HOTBACKUP
607
433
        dict_index_t*   index;
608
 
#endif /* !UNIV_HOTBACKUP */
609
434
        ulint           checksum;
610
435
        ulint           old_checksum;
611
436
        ulint           size    = zip_size;
719
544
                (ulong) mach_read_from_4(read_buf
720
545
                                         + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
721
546
 
722
 
#ifndef UNIV_HOTBACKUP
723
547
        if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE)
724
548
            == TRX_UNDO_INSERT) {
725
549
                fprintf(stderr,
730
554
                fprintf(stderr,
731
555
                        "InnoDB: Page may be an update undo log page\n");
732
556
        }
733
 
#endif /* !UNIV_HOTBACKUP */
734
557
 
735
558
        switch (fil_page_get_type(read_buf)) {
736
 
                index_id_t      index_id;
737
559
        case FIL_PAGE_INDEX:
738
 
                index_id = btr_page_get_index_id(read_buf);
739
560
                fprintf(stderr,
740
561
                        "InnoDB: Page may be an index page where"
741
 
                        " index id is %llu\n",
742
 
                        (ullint) index_id);
743
 
#ifndef UNIV_HOTBACKUP
744
 
                index = dict_index_find_on_id_low(index_id);
 
562
                        " index id is %lu %lu\n",
 
563
                        (ulong) ut_dulint_get_high(
 
564
                                btr_page_get_index_id(read_buf)),
 
565
                        (ulong) ut_dulint_get_low(
 
566
                                btr_page_get_index_id(read_buf)));
 
567
 
 
568
#ifdef UNIV_HOTBACKUP
 
569
                /* If the code is in ibbackup, dict_sys may be uninitialized,
 
570
                i.e., NULL */
 
571
 
 
572
                if (dict_sys == NULL) {
 
573
                        break;
 
574
                }
 
575
#endif /* UNIV_HOTBACKUP */
 
576
 
 
577
                index = dict_index_find_on_id_low(
 
578
                        btr_page_get_index_id(read_buf));
745
579
                if (index) {
746
580
                        fputs("InnoDB: (", stderr);
747
581
                        dict_index_name_print(stderr, NULL, index);
748
582
                        fputs(")\n", stderr);
749
583
                }
750
 
#endif /* !UNIV_HOTBACKUP */
751
584
                break;
752
585
        case FIL_PAGE_INODE:
753
586
                fputs("InnoDB: Page may be an 'inode' page\n", stderr);
792
625
        }
793
626
}
794
627
 
795
 
#ifndef UNIV_HOTBACKUP
796
 
 
797
 
# ifdef PFS_GROUP_BUFFER_SYNC
798
 
/********************************************************************//**
799
 
This function registers mutexes and rwlocks in buffer blocks with
800
 
performance schema. If PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER is
801
 
defined to be a value less than chunk->size, then only mutexes
802
 
and rwlocks in the first PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER
803
 
blocks are registered. */
804
 
static
805
 
void
806
 
pfs_register_buffer_block(
807
 
/*======================*/
808
 
        buf_chunk_t*    chunk)          /*!< in/out: chunk of buffers */
809
 
{
810
 
        ulint           i;
811
 
        ulint           num_to_register;
812
 
        buf_block_t*    block;
813
 
 
814
 
        block = chunk->blocks;
815
 
 
816
 
        num_to_register = ut_min(chunk->size,
817
 
                                 PFS_MAX_BUFFER_MUTEX_LOCK_REGISTER);
818
 
 
819
 
        for (i = 0; i < num_to_register; i++) {
820
 
                mutex_t*        mutex;
821
 
                rw_lock_t*      rwlock;
822
 
 
823
 
#  ifdef UNIV_PFS_MUTEX
824
 
                mutex = &block->mutex;
825
 
                ut_a(!mutex->pfs_psi);
826
 
                mutex->pfs_psi = (PSI_server)
827
 
                        ? PSI_server->init_mutex(buffer_block_mutex_key, mutex)
828
 
                        : NULL;
829
 
#  endif /* UNIV_PFS_MUTEX */
830
 
 
831
 
#  ifdef UNIV_PFS_RWLOCK
832
 
                rwlock = &block->lock;
833
 
                ut_a(!rwlock->pfs_psi);
834
 
                rwlock->pfs_psi = (PSI_server)
835
 
                        ? PSI_server->init_rwlock(buf_block_lock_key, rwlock)
836
 
                        : NULL;
837
 
#  endif /* UNIV_PFS_RWLOCK */
838
 
                block++;
839
 
        }
840
 
}
841
 
# endif /* PFS_GROUP_BUFFER_SYNC */
842
 
 
843
 
/********************************************************************//**
 
628
/************************************************************************
844
629
Initializes a buffer control block when the buf_pool is created. */
845
630
static
846
631
void
847
632
buf_block_init(
848
633
/*===========*/
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 */
 
634
        buf_block_t*    block,  /* in: pointer to control block */
 
635
        byte*           frame)  /* in: pointer to buffer frame */
852
636
{
853
637
        UNIV_MEM_DESC(frame, UNIV_PAGE_SIZE, block);
854
638
 
855
639
        block->frame = frame;
856
640
 
857
 
        block->page.buf_pool_index = buf_pool_index(buf_pool);
858
641
        block->page.state = BUF_BLOCK_NOT_USED;
859
642
        block->page.buf_fix_count = 0;
860
643
        block->page.io_fix = BUF_IO_NONE;
868
651
        block->check_index_page_at_flush = FALSE;
869
652
        block->index = NULL;
870
653
 
871
 
        block->is_hashed = FALSE;
872
 
 
873
654
#ifdef UNIV_DEBUG
874
655
        block->page.in_page_hash = FALSE;
875
656
        block->page.in_zip_hash = FALSE;
877
658
        block->page.in_free_list = FALSE;
878
659
        block->page.in_LRU_list = FALSE;
879
660
        block->in_unzip_LRU_list = FALSE;
880
 
#endif /* UNIV_DEBUG */
881
 
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
882
661
        block->n_pointers = 0;
883
 
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
 
662
#endif /* UNIV_DEBUG */
884
663
        page_zip_des_init(&block->page.zip);
885
664
 
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
 
 
 
665
        mutex_create(&block->mutex, SYNC_BUF_BLOCK);
 
666
 
 
667
        rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
900
668
        ut_ad(rw_lock_validate(&(block->lock)));
901
669
 
902
670
#ifdef UNIV_SYNC_DEBUG
903
 
        rw_lock_create(buf_block_debug_latch_key,
904
 
                       &block->debug_latch, SYNC_NO_ORDER_CHECK);
 
671
        rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
905
672
#endif /* UNIV_SYNC_DEBUG */
906
673
}
907
674
 
908
 
/********************************************************************//**
909
 
Allocates a chunk of buffer frames.
910
 
@return chunk, or NULL on failure */
 
675
/************************************************************************
 
676
Allocates a chunk of buffer frames. */
911
677
static
912
678
buf_chunk_t*
913
679
buf_chunk_init(
914
680
/*===========*/
915
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
916
 
        buf_chunk_t*    chunk,          /*!< out: chunk of buffers */
917
 
        ulint           mem_size)       /*!< in: requested size in bytes */
 
681
                                        /* out: chunk, or NULL on failure */
 
682
        buf_chunk_t*    chunk,          /* out: chunk of buffers */
 
683
        ulint           mem_size)       /* in: requested size in bytes */
918
684
{
919
685
        buf_block_t*    block;
920
686
        byte*           frame;
937
703
 
938
704
        /* Allocate the block descriptors from
939
705
        the start of the memory block. */
940
 
        chunk->blocks = static_cast<buf_block_struct *>(chunk->mem);
 
706
        chunk->blocks = chunk->mem;
941
707
 
942
708
        /* Align a pointer to the first frame.  Note that when
943
709
        os_large_page_size is smaller than UNIV_PAGE_SIZE,
944
710
        we may allocate one fewer block than requested.  When
945
711
        it is bigger, we may allocate more blocks than requested. */
946
712
 
947
 
        frame = static_cast<unsigned char *>(ut_align(chunk->mem, UNIV_PAGE_SIZE));
 
713
        frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
948
714
        chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
949
715
                - (frame != chunk->mem);
950
716
 
968
734
 
969
735
        for (i = chunk->size; i--; ) {
970
736
 
971
 
                buf_block_init(buf_pool, block, frame);
 
737
                buf_block_init(block, frame);
972
738
 
973
 
#ifdef HAVE_VALGRIND
 
739
#ifdef HAVE_purify
974
740
                /* Wipe contents of frame to eliminate a Purify warning */
975
741
                memset(block->frame, '\0', UNIV_PAGE_SIZE);
976
742
#endif
977
743
                /* Add the block to the free list */
978
744
                UT_LIST_ADD_LAST(list, buf_pool->free, (&block->page));
979
 
 
980
745
                ut_d(block->page.in_free_list = TRUE);
981
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
982
746
 
983
747
                block++;
984
748
                frame += UNIV_PAGE_SIZE;
985
749
        }
986
750
 
987
 
#ifdef PFS_GROUP_BUFFER_SYNC
988
 
        pfs_register_buffer_block(chunk);
989
 
#endif
990
751
        return(chunk);
991
752
}
992
753
 
993
754
#ifdef UNIV_DEBUG
994
 
/*********************************************************************//**
 
755
/*************************************************************************
995
756
Finds a block in the given buffer chunk that points to a
996
 
given compressed page.
997
 
@return buffer block pointing to the compressed page, or NULL */
 
757
given compressed page. */
998
758
static
999
759
buf_block_t*
1000
760
buf_chunk_contains_zip(
1001
761
/*===================*/
1002
 
        buf_chunk_t*    chunk,  /*!< in: chunk being checked */
1003
 
        const void*     data)   /*!< in: pointer to compressed page */
 
762
                                /* out: buffer block pointing to
 
763
                                the compressed page, or NULL */
 
764
        buf_chunk_t*    chunk,  /* in: chunk being checked */
 
765
        const void*     data)   /* in: pointer to compressed page */
1004
766
{
1005
767
        buf_block_t*    block;
1006
768
        ulint           i;
1007
769
 
 
770
        ut_ad(buf_pool);
 
771
        ut_ad(buf_pool_mutex_own());
 
772
 
1008
773
        block = chunk->blocks;
1009
774
 
1010
775
        for (i = chunk->size; i--; block++) {
1017
782
        return(NULL);
1018
783
}
1019
784
 
1020
 
/*********************************************************************//**
 
785
/*************************************************************************
1021
786
Finds a block in the buffer pool that points to a
1022
 
given compressed page.
1023
 
@return buffer block pointing to the compressed page, or NULL */
 
787
given compressed page. */
1024
788
UNIV_INTERN
1025
789
buf_block_t*
1026
790
buf_pool_contains_zip(
1027
791
/*==================*/
1028
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1029
 
        const void*     data)           /*!< in: pointer to compressed page */
 
792
                                /* out: buffer block pointing to
 
793
                                the compressed page, or NULL */
 
794
        const void*     data)   /* in: pointer to compressed page */
1030
795
{
1031
796
        ulint           n;
1032
797
        buf_chunk_t*    chunk = buf_pool->chunks;
1033
798
 
1034
 
        ut_ad(buf_pool);
1035
 
        ut_ad(buf_pool_mutex_own(buf_pool));
1036
799
        for (n = buf_pool->n_chunks; n--; chunk++) {
1037
 
 
1038
800
                buf_block_t* block = buf_chunk_contains_zip(chunk, data);
1039
801
 
1040
802
                if (block) {
1046
808
}
1047
809
#endif /* UNIV_DEBUG */
1048
810
 
1049
 
/*********************************************************************//**
1050
 
Checks that all file pages in the buffer chunk are in a replaceable state.
1051
 
@return address of a non-free block, or NULL if all freed */
 
811
/*************************************************************************
 
812
Checks that all file pages in the buffer chunk are in a replaceable state. */
1052
813
static
1053
814
const buf_block_t*
1054
815
buf_chunk_not_freed(
1055
816
/*================*/
1056
 
        buf_chunk_t*    chunk)  /*!< in: chunk being checked */
 
817
                                /* out: address of a non-free block,
 
818
                                or NULL if all freed */
 
819
        buf_chunk_t*    chunk)  /* in: chunk being checked */
1057
820
{
1058
821
        buf_block_t*    block;
1059
822
        ulint           i;
1060
823
 
 
824
        ut_ad(buf_pool);
 
825
        ut_ad(buf_pool_mutex_own());
 
826
 
1061
827
        block = chunk->blocks;
1062
828
 
1063
829
        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);
 
830
                mutex_enter(&block->mutex);
 
831
 
 
832
                if (buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
 
833
                    && !buf_flush_ready_for_replace(&block->page)) {
 
834
 
1084
835
                        mutex_exit(&block->mutex);
1085
 
 
1086
 
                        if (!ready) {
1087
 
 
1088
 
                                return(block);
1089
 
                        }
1090
 
 
1091
 
                        break;
 
836
                        return(block);
1092
837
                }
 
838
 
 
839
                mutex_exit(&block->mutex);
1093
840
        }
1094
841
 
1095
842
        return(NULL);
1096
843
}
1097
844
 
1098
 
/*********************************************************************//**
1099
 
Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state.
1100
 
@return TRUE if all freed */
 
845
/*************************************************************************
 
846
Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state. */
1101
847
static
1102
848
ibool
1103
849
buf_chunk_all_free(
1104
850
/*===============*/
1105
 
        const buf_chunk_t*      chunk)  /*!< in: chunk being checked */
 
851
                                        /* out: TRUE if all freed */
 
852
        const buf_chunk_t*      chunk)  /* in: chunk being checked */
1106
853
{
1107
854
        const buf_block_t*      block;
1108
855
        ulint                   i;
1109
856
 
 
857
        ut_ad(buf_pool);
 
858
        ut_ad(buf_pool_mutex_own());
 
859
 
1110
860
        block = chunk->blocks;
1111
861
 
1112
862
        for (i = chunk->size; i--; block++) {
1120
870
        return(TRUE);
1121
871
}
1122
872
 
1123
 
/********************************************************************//**
 
873
/************************************************************************
1124
874
Frees a chunk of buffer frames. */
1125
875
static
1126
876
void
1127
877
buf_chunk_free(
1128
878
/*===========*/
1129
 
        buf_pool_t*     buf_pool,       /*!< in: buffer pool instance */
1130
 
        buf_chunk_t*    chunk)          /*!< out: chunk of buffers */
 
879
        buf_chunk_t*    chunk)          /* out: chunk of buffers */
1131
880
{
1132
881
        buf_block_t*            block;
1133
882
        const buf_block_t*      block_end;
1134
883
 
1135
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
884
        ut_ad(buf_pool_mutex_own());
1136
885
 
1137
886
        block_end = chunk->blocks + chunk->size;
1138
887
 
1159
908
        os_mem_free_large(chunk->mem, chunk->mem_size);
1160
909
}
1161
910
 
1162
 
/********************************************************************//**
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
 
{
 
911
/************************************************************************
 
912
Creates the buffer pool. */
 
913
UNIV_INTERN
 
914
buf_pool_t*
 
915
buf_pool_init(void)
 
916
/*===============*/
 
917
                                /* out, own: buf_pool object, NULL if not
 
918
                                enough memory or error */
 
919
{
 
920
        buf_chunk_t*    chunk;
1198
921
        ulint           i;
1199
 
        buf_chunk_t*    chunk;
 
922
 
 
923
        buf_pool = mem_zalloc(sizeof(buf_pool_t));
1200
924
 
1201
925
        /* 1. Initialize general fields
1202
926
        ------------------------------- */
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();
 
927
        mutex_create(&buf_pool_mutex, SYNC_BUF_POOL);
 
928
        mutex_create(&buf_pool_zip_mutex, SYNC_BUF_BLOCK);
 
929
 
 
930
        buf_pool_mutex_enter();
 
931
 
 
932
        buf_pool->n_chunks = 1;
 
933
        buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
 
934
 
 
935
        UT_LIST_INIT(buf_pool->free);
 
936
 
 
937
        if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
 
938
                mem_free(chunk);
 
939
                mem_free(buf_pool);
 
940
                buf_pool = NULL;
 
941
                return(NULL);
1235
942
        }
 
943
 
 
944
        srv_buf_pool_old_size = srv_buf_pool_size;
 
945
        buf_pool->curr_size = chunk->size;
 
946
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
947
 
 
948
        buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
 
949
        buf_pool->zip_hash = hash_create(2 * buf_pool->curr_size);
 
950
 
 
951
        buf_pool->last_printout_time = time(NULL);
 
952
 
1236
953
        /* 2. Initialize flushing fields
1237
954
        -------------------------------- */
1238
955
 
1239
 
        mutex_create(flush_list_mutex_key, &buf_pool->flush_list_mutex,
1240
 
                     SYNC_BUF_FLUSH_LIST);
1241
 
 
1242
956
        for (i = BUF_FLUSH_LRU; i < BUF_FLUSH_N_TYPES; i++) {
1243
957
                buf_pool->no_flush[i] = os_event_create(NULL);
1244
958
        }
1245
959
 
 
960
        buf_pool->ulint_clock = 1;
 
961
 
1246
962
        /* 3. Initialize LRU fields
1247
963
        --------------------------- */
1248
 
 
1249
 
        /* All fields are initialized by mem_zalloc(). */
1250
 
 
1251
 
        buf_pool_mutex_exit(buf_pool);
1252
 
 
1253
 
        return(DB_SUCCESS);
 
964
        /* All fields are initialized by mem_zalloc(). */
 
965
 
 
966
        buf_pool_mutex_exit();
 
967
 
 
968
        btr_search_sys_create(buf_pool->curr_size
 
969
                              * UNIV_PAGE_SIZE / sizeof(void*) / 64);
 
970
 
 
971
        /* 4. Initialize the buddy allocator fields */
 
972
        /* All fields are initialized by mem_zalloc(). */
 
973
 
 
974
        return(buf_pool);
1254
975
}
1255
976
 
1256
 
/********************************************************************//**
1257
 
free one buffer pool instance */
1258
 
static
 
977
/************************************************************************
 
978
Frees the buffer pool at shutdown.  This must not be invoked before
 
979
freeing all mutexes. */
 
980
UNIV_INTERN
1259
981
void
1260
 
buf_pool_free_instance(
1261
 
/*===================*/
1262
 
        buf_pool_t*     buf_pool)       /* in,own: buffer pool instance
1263
 
                                        to free */
 
982
buf_pool_free(void)
 
983
/*===============*/
1264
984
{
1265
985
        buf_chunk_t*    chunk;
1266
986
        buf_chunk_t*    chunks;
1274
994
                os_mem_free_large(chunk->mem, chunk->mem_size);
1275
995
        }
1276
996
 
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
 
 
1416
 
/********************************************************************//**
1417
 
Drops the adaptive hash index.  To prevent a livelock, this function
1418
 
is only to be called while holding btr_search_latch and while
1419
 
btr_search_enabled == FALSE. */
1420
 
UNIV_INTERN
1421
 
void
1422
 
buf_pool_drop_hash_index(void)
1423
 
/*==========================*/
1424
 
{
1425
 
        ibool           released_search_latch;
1426
 
 
1427
 
#ifdef UNIV_SYNC_DEBUG
1428
 
        ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
1429
 
#endif /* UNIV_SYNC_DEBUG */
1430
 
        ut_ad(!btr_search_enabled);
1431
 
 
1432
 
        do {
1433
 
                ulint   i;
1434
 
 
1435
 
                released_search_latch = FALSE;
1436
 
 
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);
1444
 
                }
1445
 
 
1446
 
        } while (released_search_latch);
1447
 
}
1448
 
 
1449
 
/********************************************************************//**
 
997
        buf_pool->n_chunks = 0;
 
998
}
 
999
 
 
1000
/************************************************************************
1450
1001
Relocate a buffer control block.  Relocates the block on the LRU list
1451
1002
and in buf_pool->page_hash.  Does not relocate bpage->list.
1452
1003
The caller must take care of relocating bpage->list. */
1454
1005
void
1455
1006
buf_relocate(
1456
1007
/*=========*/
1457
 
        buf_page_t*     bpage,  /*!< in/out: control block being relocated;
 
1008
        buf_page_t*     bpage,  /* in/out: control block being relocated;
1458
1009
                                buf_page_get_state(bpage) must be
1459
1010
                                BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_ZIP_PAGE */
1460
 
        buf_page_t*     dpage)  /*!< in/out: destination control block */
 
1011
        buf_page_t*     dpage)  /* in/out: destination control block */
1461
1012
{
1462
1013
        buf_page_t*     b;
1463
1014
        ulint           fold;
1464
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
1465
1015
 
1466
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
1016
        ut_ad(buf_pool_mutex_own());
1467
1017
        ut_ad(mutex_own(buf_page_get_mutex(bpage)));
1468
1018
        ut_a(buf_page_get_io_fix(bpage) == BUF_IO_NONE);
1469
1019
        ut_a(bpage->buf_fix_count == 0);
1470
1020
        ut_ad(bpage->in_LRU_list);
1471
1021
        ut_ad(!bpage->in_zip_hash);
1472
1022
        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));
 
1023
        ut_ad(bpage == buf_page_hash_get(bpage->space, bpage->offset));
1476
1024
#ifdef UNIV_DEBUG
1477
1025
        switch (buf_page_get_state(bpage)) {
1478
1026
        case BUF_BLOCK_ZIP_FREE:
1508
1056
#ifdef UNIV_LRU_DEBUG
1509
1057
                /* buf_pool->LRU_old must be the first item in the LRU list
1510
1058
                whose "old" flag is set. */
1511
 
                ut_a(buf_pool->LRU_old->old);
1512
1059
                ut_a(!UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)
1513
1060
                     || !UT_LIST_GET_PREV(LRU, buf_pool->LRU_old)->old);
1514
1061
                ut_a(!UT_LIST_GET_NEXT(LRU, buf_pool->LRU_old)
1515
1062
                     || 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
1063
#endif /* UNIV_LRU_DEBUG */
1521
1064
        }
1522
1065
 
1523
 
        ut_d(UT_LIST_VALIDATE(LRU, buf_page_t, buf_pool->LRU,
1524
 
                              ut_ad(ut_list_node_313->in_LRU_list)));
 
1066
        ut_d(UT_LIST_VALIDATE(LRU, buf_page_t, buf_pool->LRU));
1525
1067
 
1526
1068
        /* relocate buf_pool->page_hash */
1527
1069
        fold = buf_page_address_fold(bpage->space, bpage->offset);
1528
1070
 
1529
1071
        HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
1530
1072
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
 
1073
 
 
1074
        UNIV_MEM_INVALID(bpage, sizeof *bpage);
1531
1075
}
1532
1076
 
1533
 
/********************************************************************//**
1534
 
Shrinks a buffer pool instance. */
 
1077
/************************************************************************
 
1078
Shrinks the buffer pool. */
1535
1079
static
1536
1080
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 */
 
1081
buf_pool_shrink(
 
1082
/*============*/
 
1083
                                /* out: TRUE if shrunk */
 
1084
        ulint   chunk_size)     /* in: number of pages to remove */
1541
1085
{
1542
1086
        buf_chunk_t*    chunks;
1543
1087
        buf_chunk_t*    chunk;
1546
1090
        buf_chunk_t*    max_chunk;
1547
1091
        buf_chunk_t*    max_free_chunk;
1548
1092
 
1549
 
        ut_ad(!buf_pool_mutex_own(buf_pool));
 
1093
        ut_ad(!buf_pool_mutex_own());
1550
1094
 
1551
1095
try_again:
1552
1096
        btr_search_disable(); /* Empty the adaptive hash index again */
1553
 
        buf_pool_mutex_enter(buf_pool);
 
1097
        buf_pool_mutex_enter();
1554
1098
 
1555
1099
shrink_again:
1556
1100
        if (buf_pool->n_chunks <= 1) {
1613
1157
 
1614
1158
                        mutex_enter(&block->mutex);
1615
1159
                        /* The following calls will temporarily
1616
 
                        release block->mutex and buf_pool->mutex.
 
1160
                        release block->mutex and buf_pool_mutex.
1617
1161
                        Therefore, we have to always retry,
1618
1162
                        even if !dirty && !nonfree. */
1619
1163
 
1629
1173
                        mutex_exit(&block->mutex);
1630
1174
                }
1631
1175
 
1632
 
                buf_pool_mutex_exit(buf_pool);
 
1176
                buf_pool_mutex_exit();
1633
1177
 
1634
1178
                /* Request for a flush of the chunk if it helps.
1635
1179
                Do not flush if there are non-free blocks, since
1638
1182
                        /* Avoid busy-waiting. */
1639
1183
                        os_thread_sleep(100000);
1640
1184
                } else if (dirty
1641
 
                           && buf_flush_LRU(buf_pool, dirty)
1642
 
                              == ULINT_UNDEFINED) {
 
1185
                           && buf_flush_batch(BUF_FLUSH_LRU, dirty, 0)
 
1186
                           == ULINT_UNDEFINED) {
1643
1187
 
1644
 
                        buf_flush_wait_batch_end(buf_pool, BUF_FLUSH_LRU);
 
1188
                        buf_flush_wait_batch_end(BUF_FLUSH_LRU);
1645
1189
                }
1646
1190
 
1647
1191
                goto try_again;
1650
1194
        max_size = max_free_size;
1651
1195
        max_chunk = max_free_chunk;
1652
1196
 
1653
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1197
        srv_buf_pool_old_size = srv_buf_pool_size;
1654
1198
 
1655
1199
        /* 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));
 
1200
        chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
1657
1201
        memcpy(chunks, buf_pool->chunks,
1658
1202
               (max_chunk - buf_pool->chunks) * sizeof *chunks);
1659
1203
        memcpy(chunks + (max_chunk - buf_pool->chunks),
1662
1206
               - (max_chunk + 1));
1663
1207
        ut_a(buf_pool->curr_size > max_chunk->size);
1664
1208
        buf_pool->curr_size -= max_chunk->size;
1665
 
        buf_pool->curr_pool_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
 
1209
        srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
1666
1210
        chunk_size -= max_chunk->size;
1667
 
        buf_chunk_free(buf_pool, max_chunk);
 
1211
        buf_chunk_free(max_chunk);
1668
1212
        mem_free(buf_pool->chunks);
1669
1213
        buf_pool->chunks = chunks;
1670
1214
        buf_pool->n_chunks--;
1674
1218
 
1675
1219
                goto shrink_again;
1676
1220
        }
1677
 
        goto func_exit;
1678
1221
 
1679
1222
func_done:
1680
 
        buf_pool->old_pool_size = buf_pool->curr_pool_size;
 
1223
        srv_buf_pool_old_size = srv_buf_pool_size;
1681
1224
func_exit:
1682
 
        buf_pool_mutex_exit(buf_pool);
 
1225
        buf_pool_mutex_exit();
1683
1226
        btr_search_enable();
1684
1227
}
1685
1228
 
1686
 
/********************************************************************//**
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 */
 
1229
/************************************************************************
 
1230
Rebuild buf_pool->page_hash. */
 
1231
static
 
1232
void
 
1233
buf_pool_page_hash_rebuild(void)
 
1234
/*============================*/
1715
1235
{
1716
1236
        ulint           i;
1717
 
        buf_page_t*     b;
1718
 
        buf_chunk_t*    chunk;
1719
1237
        ulint           n_chunks;
 
1238
        buf_chunk_t*    chunk;
 
1239
        hash_table_t*   page_hash;
1720
1240
        hash_table_t*   zip_hash;
1721
 
        hash_table_t*   page_hash;
 
1241
        buf_page_t*     b;
1722
1242
 
1723
 
        buf_pool_mutex_enter(buf_pool);
 
1243
        buf_pool_mutex_enter();
1724
1244
 
1725
1245
        /* Free, create, and populate the hash table. */
1726
1246
        hash_table_free(buf_pool->page_hash);
1773
1293
                            buf_page_address_fold(b->space, b->offset), b);
1774
1294
        }
1775
1295
 
1776
 
        buf_flush_list_mutex_enter(buf_pool);
1777
1296
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
1778
1297
             b = UT_LIST_GET_NEXT(list, b)) {
1779
1298
                ut_ad(b->in_flush_list);
1801
1320
                }
1802
1321
        }
1803
1322
 
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();
1978
 
}
1979
 
 
1980
 
/********************************************************************//**
 
1323
        buf_pool_mutex_exit();
 
1324
}
 
1325
 
 
1326
/************************************************************************
1981
1327
Resizes the buffer pool. */
1982
1328
UNIV_INTERN
1983
1329
void
1984
1330
buf_pool_resize(void)
1985
1331
/*=================*/
1986
1332
{
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
 
 
 
1333
        buf_pool_mutex_enter();
 
1334
 
 
1335
        if (srv_buf_pool_old_size == srv_buf_pool_size) {
 
1336
 
 
1337
                buf_pool_mutex_exit();
2025
1338
                return;
2026
1339
        }
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(
 
1340
 
 
1341
        if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
 
1342
 
 
1343
                buf_pool_mutex_exit();
 
1344
 
 
1345
                /* Disable adaptive hash indexes and empty the index
 
1346
                in order to free up memory in the buffer pool chunks. */
 
1347
                buf_pool_shrink((srv_buf_pool_curr_size - srv_buf_pool_size)
 
1348
                                / UNIV_PAGE_SIZE);
 
1349
        } else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
 
1350
 
 
1351
                /* Enlarge the buffer pool by at least one megabyte */
 
1352
 
 
1353
                ulint           mem_size
 
1354
                        = srv_buf_pool_size - srv_buf_pool_curr_size;
 
1355
                buf_chunk_t*    chunks;
 
1356
                buf_chunk_t*    chunk;
 
1357
 
 
1358
                chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
 
1359
 
 
1360
                memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
 
1361
                       * sizeof *chunks);
 
1362
 
 
1363
                chunk = &chunks[buf_pool->n_chunks];
 
1364
 
 
1365
                if (!buf_chunk_init(chunk, mem_size)) {
 
1366
                        mem_free(chunks);
 
1367
                } else {
 
1368
                        buf_pool->curr_size += chunk->size;
 
1369
                        srv_buf_pool_curr_size = buf_pool->curr_size
 
1370
                                * UNIV_PAGE_SIZE;
 
1371
                        mem_free(buf_pool->chunks);
 
1372
                        buf_pool->chunks = chunks;
 
1373
                        buf_pool->n_chunks++;
 
1374
                }
 
1375
 
 
1376
                srv_buf_pool_old_size = srv_buf_pool_size;
 
1377
                buf_pool_mutex_exit();
 
1378
        }
 
1379
 
 
1380
        buf_pool_page_hash_rebuild();
 
1381
}
 
1382
 
 
1383
/************************************************************************
 
1384
Moves to the block to the start of the LRU list if there is a danger
 
1385
that the block would drift out of the buffer pool. */
 
1386
UNIV_INLINE
 
1387
void
 
1388
buf_block_make_young(
2059
1389
/*=================*/
2060
 
        ulint   space,  /*!< in: space id */
2061
 
        ulint   offset) /*!< in: page number */
 
1390
        buf_page_t*     bpage)  /* in: block to make younger */
2062
1391
{
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
 
                }
 
1392
        ut_ad(!buf_pool_mutex_own());
 
1393
 
 
1394
        /* Note that we read freed_page_clock's without holding any mutex:
 
1395
        this is allowed since the result is used only in heuristics */
 
1396
 
 
1397
        if (buf_page_peek_if_too_old(bpage)) {
 
1398
 
 
1399
                buf_pool_mutex_enter();
 
1400
                /* There has been freeing activity in the LRU list:
 
1401
                best to move to the head of the LRU list */
 
1402
 
 
1403
                buf_LRU_make_block_young(bpage);
 
1404
                buf_pool_mutex_exit();
2086
1405
        }
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
 
}
2119
 
 
2120
 
/********************************************************************//**
 
1406
}
 
1407
 
 
1408
/************************************************************************
2121
1409
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
 
1410
function can be used to prevent an important page from from slipping out of
2123
1411
the buffer pool. */
2124
1412
UNIV_INTERN
2125
1413
void
2126
1414
buf_page_make_young(
2127
1415
/*================*/
2128
 
        buf_page_t*     bpage)  /*!< in: buffer block of a file page */
 
1416
        buf_page_t*     bpage)  /* in: buffer block of a file page */
2129
1417
{
2130
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
2131
 
 
2132
 
        buf_pool_mutex_enter(buf_pool);
 
1418
        buf_pool_mutex_enter();
2133
1419
 
2134
1420
        ut_a(buf_page_in_file(bpage));
2135
1421
 
2136
1422
        buf_LRU_make_block_young(bpage);
2137
1423
 
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
 
        }
2171
 
}
2172
 
 
2173
 
/********************************************************************//**
 
1424
        buf_pool_mutex_exit();
 
1425
}
 
1426
 
 
1427
/************************************************************************
2174
1428
Resets the check_index_page_at_flush field of a page if found in the buffer
2175
1429
pool. */
2176
1430
UNIV_INTERN
2177
1431
void
2178
1432
buf_reset_check_index_page_at_flush(
2179
1433
/*================================*/
2180
 
        ulint   space,  /*!< in: space id */
2181
 
        ulint   offset) /*!< in: page number */
 
1434
        ulint   space,  /* in: space id */
 
1435
        ulint   offset) /* in: page number */
2182
1436
{
2183
1437
        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);
 
1438
 
 
1439
        buf_pool_mutex_enter();
 
1440
 
 
1441
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2189
1442
 
2190
1443
        if (block && buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE) {
2191
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2192
1444
                block->check_index_page_at_flush = FALSE;
2193
1445
        }
2194
1446
 
2195
 
        buf_pool_mutex_exit(buf_pool);
 
1447
        buf_pool_mutex_exit();
2196
1448
}
2197
1449
 
2198
 
/********************************************************************//**
 
1450
/************************************************************************
2199
1451
Returns the current state of is_hashed of a page. FALSE if the page is
2200
1452
not in the pool. NOTE that this operation does not fix the page in the
2201
 
pool if it is found there.
2202
 
@return TRUE if page hash index is built in search system */
 
1453
pool if it is found there. */
2203
1454
UNIV_INTERN
2204
1455
ibool
2205
1456
buf_page_peek_if_search_hashed(
2206
1457
/*===========================*/
2207
 
        ulint   space,  /*!< in: space id */
2208
 
        ulint   offset) /*!< in: page number */
 
1458
                        /* out: TRUE if page hash index is built in search
 
1459
                        system */
 
1460
        ulint   space,  /* in: space id */
 
1461
        ulint   offset) /* in: page number */
2209
1462
{
2210
1463
        buf_block_t*    block;
2211
1464
        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);
 
1465
 
 
1466
        buf_pool_mutex_enter();
 
1467
 
 
1468
        block = (buf_block_t*) buf_page_hash_get(space, offset);
2217
1469
 
2218
1470
        if (!block || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2219
1471
                is_hashed = FALSE;
2220
1472
        } else {
2221
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
2222
1473
                is_hashed = block->is_hashed;
2223
1474
        }
2224
1475
 
2225
 
        buf_pool_mutex_exit(buf_pool);
 
1476
        buf_pool_mutex_exit();
2226
1477
 
2227
1478
        return(is_hashed);
2228
1479
}
2229
1480
 
2230
1481
#ifdef UNIV_DEBUG_FILE_ACCESSES
2231
 
/********************************************************************//**
 
1482
/************************************************************************
2232
1483
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
2233
1484
This function should be called when we free a file page and want the
2234
1485
debug version to check that it is not accessed any more unless
2235
 
reallocated.
2236
 
@return control block if found in page hash table, otherwise NULL */
 
1486
reallocated. */
2237
1487
UNIV_INTERN
2238
1488
buf_page_t*
2239
1489
buf_page_set_file_page_was_freed(
2240
1490
/*=============================*/
2241
 
        ulint   space,  /*!< in: space id */
2242
 
        ulint   offset) /*!< in: page number */
 
1491
                        /* out: control block if found in page hash table,
 
1492
                        otherwise NULL */
 
1493
        ulint   space,  /* in: space id */
 
1494
        ulint   offset) /* in: page number */
2243
1495
{
2244
1496
        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);
 
1497
 
 
1498
        buf_pool_mutex_enter();
 
1499
 
 
1500
        bpage = buf_page_hash_get(space, offset);
2250
1501
 
2251
1502
        if (bpage) {
2252
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2253
1503
                bpage->file_page_was_freed = TRUE;
2254
1504
        }
2255
1505
 
2256
 
        buf_pool_mutex_exit(buf_pool);
 
1506
        buf_pool_mutex_exit();
2257
1507
 
2258
1508
        return(bpage);
2259
1509
}
2260
1510
 
2261
 
/********************************************************************//**
 
1511
/************************************************************************
2262
1512
Sets file_page_was_freed FALSE if the page is found in the buffer pool.
2263
1513
This function should be called when we free a file page and want the
2264
1514
debug version to check that it is not accessed any more unless
2265
 
reallocated.
2266
 
@return control block if found in page hash table, otherwise NULL */
 
1515
reallocated. */
2267
1516
UNIV_INTERN
2268
1517
buf_page_t*
2269
1518
buf_page_reset_file_page_was_freed(
2270
1519
/*===============================*/
2271
 
        ulint   space,  /*!< in: space id */
2272
 
        ulint   offset) /*!< in: page number */
 
1520
                        /* out: control block if found in page hash table,
 
1521
                        otherwise NULL */
 
1522
        ulint   space,  /* in: space id */
 
1523
        ulint   offset) /* in: page number */
2273
1524
{
2274
1525
        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);
 
1526
 
 
1527
        buf_pool_mutex_enter();
 
1528
 
 
1529
        bpage = buf_page_hash_get(space, offset);
2280
1530
 
2281
1531
        if (bpage) {
2282
 
                ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2283
1532
                bpage->file_page_was_freed = FALSE;
2284
1533
        }
2285
1534
 
2286
 
        buf_pool_mutex_exit(buf_pool);
 
1535
        buf_pool_mutex_exit();
2287
1536
 
2288
1537
        return(bpage);
2289
1538
}
2290
1539
#endif /* UNIV_DEBUG_FILE_ACCESSES */
2291
1540
 
2292
 
/********************************************************************//**
 
1541
/************************************************************************
2293
1542
Get read access to a compressed page (usually of type
2294
1543
FIL_PAGE_TYPE_ZBLOB or FIL_PAGE_TYPE_ZBLOB2).
2295
1544
The page must be released with buf_page_release_zip().
2296
1545
NOTE: the page is not protected by any latch.  Mutual exclusion has to
2297
1546
be implemented at a higher level.  In other words, all possible
2298
1547
accesses to a given page through this function must be protected by
2299
 
the same set of mutexes or latches.
2300
 
@return pointer to the block */
 
1548
the same set of mutexes or latches. */
2301
1549
UNIV_INTERN
2302
1550
buf_page_t*
2303
1551
buf_page_get_zip(
2304
1552
/*=============*/
2305
 
        ulint           space,  /*!< in: space id */
2306
 
        ulint           zip_size,/*!< in: compressed page size */
2307
 
        ulint           offset) /*!< in: page number */
 
1553
                                /* out: pointer to the block */
 
1554
        ulint           space,  /* in: space id */
 
1555
        ulint           zip_size,/* in: compressed page size */
 
1556
        ulint           offset) /* in: page number */
2308
1557
{
2309
1558
        buf_page_t*     bpage;
2310
1559
        mutex_t*        block_mutex;
2311
1560
        ibool           must_read;
2312
 
        unsigned        access_time;
2313
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2314
1561
 
2315
1562
#ifndef UNIV_LOG_DEBUG
2316
1563
        ut_ad(!ibuf_inside());
2317
1564
#endif
2318
 
        buf_pool->stat.n_page_gets++;
 
1565
        buf_pool->n_page_gets++;
2319
1566
 
2320
1567
        for (;;) {
2321
 
                buf_pool_mutex_enter(buf_pool);
 
1568
                buf_pool_mutex_enter();
2322
1569
lookup:
2323
 
                bpage = buf_page_hash_get(buf_pool, space, offset);
 
1570
                bpage = buf_page_hash_get(space, offset);
2324
1571
                if (bpage) {
2325
 
                        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
2326
1572
                        break;
2327
1573
                }
2328
1574
 
2329
1575
                /* Page not in buf_pool: needs to be read from file */
2330
1576
 
2331
 
                buf_pool_mutex_exit(buf_pool);
 
1577
                buf_pool_mutex_exit();
2332
1578
 
2333
1579
                buf_read_page(space, zip_size, offset);
2334
1580
 
2339
1585
 
2340
1586
        if (UNIV_UNLIKELY(!bpage->zip.data)) {
2341
1587
                /* There is no compressed page. */
2342
 
err_exit:
2343
 
                buf_pool_mutex_exit(buf_pool);
 
1588
                buf_pool_mutex_exit();
2344
1589
                return(NULL);
2345
1590
        }
2346
1591
 
2347
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, bpage));
 
1592
        block_mutex = buf_page_get_mutex(bpage);
 
1593
        mutex_enter(block_mutex);
2348
1594
 
2349
1595
        switch (buf_page_get_state(bpage)) {
2350
1596
        case BUF_BLOCK_NOT_USED:
2352
1598
        case BUF_BLOCK_MEMORY:
2353
1599
        case BUF_BLOCK_REMOVE_HASH:
2354
1600
        case BUF_BLOCK_ZIP_FREE:
 
1601
                ut_error;
2355
1602
                break;
2356
1603
        case BUF_BLOCK_ZIP_PAGE:
2357
1604
        case BUF_BLOCK_ZIP_DIRTY:
2358
 
                block_mutex = &buf_pool->zip_mutex;
2359
 
                mutex_enter(block_mutex);
2360
1605
                bpage->buf_fix_count++;
2361
 
                goto got_block;
 
1606
                break;
2362
1607
        case BUF_BLOCK_FILE_PAGE:
2363
 
                block_mutex = &((buf_block_t*) bpage)->mutex;
2364
 
                mutex_enter(block_mutex);
2365
 
 
2366
1608
                /* Discard the uncompressed page frame if possible. */
2367
1609
                if (buf_LRU_free_block(bpage, FALSE, NULL)
2368
1610
                    == BUF_LRU_FREED) {
2373
1615
 
2374
1616
                buf_block_buf_fix_inc((buf_block_t*) bpage,
2375
1617
                                      __FILE__, __LINE__);
2376
 
                goto got_block;
 
1618
                break;
2377
1619
        }
2378
1620
 
2379
 
        ut_error;
2380
 
        goto err_exit;
2381
 
 
2382
 
got_block:
2383
1621
        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);
 
1622
 
 
1623
        buf_pool_mutex_exit();
 
1624
 
 
1625
        buf_page_set_accessed(bpage, TRUE);
2387
1626
 
2388
1627
        mutex_exit(block_mutex);
2389
1628
 
2390
 
        buf_page_set_accessed_make_young(bpage, access_time);
 
1629
        buf_block_make_young(bpage);
2391
1630
 
2392
1631
#ifdef UNIV_DEBUG_FILE_ACCESSES
2393
1632
        ut_a(!bpage->file_page_was_freed);
2426
1665
        return(bpage);
2427
1666
}
2428
1667
 
2429
 
/********************************************************************//**
 
1668
/************************************************************************
2430
1669
Initialize some fields of a control block. */
2431
1670
UNIV_INLINE
2432
1671
void
2433
1672
buf_block_init_low(
2434
1673
/*===============*/
2435
 
        buf_block_t*    block)  /*!< in: block to init */
 
1674
        buf_block_t*    block)  /* in: block to init */
2436
1675
{
2437
1676
        block->check_index_page_at_flush = FALSE;
2438
1677
        block->index            = NULL;
2443
1682
        block->n_bytes          = 0;
2444
1683
        block->left_side        = TRUE;
2445
1684
}
2446
 
#endif /* !UNIV_HOTBACKUP */
2447
1685
 
2448
 
/********************************************************************//**
2449
 
Decompress a block.
2450
 
@return TRUE if successful */
2451
 
UNIV_INTERN
 
1686
/************************************************************************
 
1687
Decompress a block. */
 
1688
static
2452
1689
ibool
2453
1690
buf_zip_decompress(
2454
1691
/*===============*/
2455
 
        buf_block_t*    block,  /*!< in/out: block */
2456
 
        ibool           check)  /*!< in: TRUE=verify the page checksum */
 
1692
                                /* out: TRUE if successful */
 
1693
        buf_block_t*    block,  /* in/out: block */
 
1694
        ibool           check)  /* in: TRUE=verify the page checksum */
2457
1695
{
2458
 
        const byte*     frame           = block->page.zip.data;
2459
 
        ulint           stamp_checksum  = mach_read_from_4(
2460
 
                frame + FIL_PAGE_SPACE_OR_CHKSUM);
 
1696
        const byte* frame = block->page.zip.data;
2461
1697
 
2462
1698
        ut_ad(buf_block_get_zip_size(block));
2463
1699
        ut_a(buf_block_get_space(block) != 0);
2464
1700
 
2465
 
        if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
 
1701
        if (UNIV_LIKELY(check)) {
 
1702
                ulint   stamp_checksum  = mach_read_from_4(
 
1703
                        frame + FIL_PAGE_SPACE_OR_CHKSUM);
2466
1704
                ulint   calc_checksum   = page_zip_calc_checksum(
2467
1705
                        frame, page_zip_get_size(&block->page.zip));
2468
1706
 
2480
1718
        switch (fil_page_get_type(frame)) {
2481
1719
        case FIL_PAGE_INDEX:
2482
1720
                if (page_zip_decompress(&block->page.zip,
2483
 
                                        block->frame, TRUE)) {
 
1721
                                        block->frame)) {
2484
1722
                        return(TRUE);
2485
1723
                }
2486
1724
 
2511
1749
        return(FALSE);
2512
1750
}
2513
1751
 
2514
 
#ifndef UNIV_HOTBACKUP
2515
 
/*******************************************************************//**
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
2520
 
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 */
2526
 
{
2527
 
        buf_chunk_t*    chunk;
2528
 
        ulint           i;
2529
 
 
2530
 
        /* TODO: protect buf_pool->chunks with a mutex (it will
2531
 
        currently remain constant after buf_pool_init()) */
2532
 
        for (chunk = buf_pool->chunks, i = buf_pool->n_chunks; i--; chunk++) {
2533
 
                lint    offs = ptr - chunk->blocks->frame;
2534
 
 
2535
 
                if (UNIV_UNLIKELY(offs < 0)) {
2536
 
 
2537
 
                        continue;
2538
 
                }
2539
 
 
2540
 
                offs >>= UNIV_PAGE_SIZE_SHIFT;
2541
 
 
2542
 
                if (UNIV_LIKELY((ulint) offs < chunk->size)) {
2543
 
                        buf_block_t*    block = &chunk->blocks[offs];
2544
 
 
2545
 
                        /* The function buf_chunk_init() invokes
2546
 
                        buf_block_init() so that block[n].frame ==
2547
 
                        block->frame + n * UNIV_PAGE_SIZE.  Check it. */
2548
 
                        ut_ad(block->frame == page_align(ptr));
2549
 
#ifdef UNIV_DEBUG
2550
 
                        /* A thread that updates these fields must
2551
 
                        hold buf_pool->mutex and block->mutex.  Acquire
2552
 
                        only the latter. */
2553
 
                        mutex_enter(&block->mutex);
2554
 
 
2555
 
                        switch (buf_block_get_state(block)) {
2556
 
                        case BUF_BLOCK_ZIP_FREE:
2557
 
                        case BUF_BLOCK_ZIP_PAGE:
2558
 
                        case BUF_BLOCK_ZIP_DIRTY:
2559
 
                                /* These types should only be used in
2560
 
                                the compressed buffer pool, whose
2561
 
                                memory is allocated from
2562
 
                                buf_pool->chunks, in UNIV_PAGE_SIZE
2563
 
                                blocks flagged as BUF_BLOCK_MEMORY. */
2564
 
                                ut_error;
2565
 
                                break;
2566
 
                        case BUF_BLOCK_NOT_USED:
2567
 
                        case BUF_BLOCK_READY_FOR_USE:
2568
 
                        case BUF_BLOCK_MEMORY:
2569
 
                                /* Some data structures contain
2570
 
                                "guess" pointers to file pages.  The
2571
 
                                file pages may have been freed and
2572
 
                                reused.  Do not complain. */
2573
 
                                break;
2574
 
                        case BUF_BLOCK_REMOVE_HASH:
2575
 
                                /* buf_LRU_block_remove_hashed_page()
2576
 
                                will overwrite the FIL_PAGE_OFFSET and
2577
 
                                FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID with
2578
 
                                0xff and set the state to
2579
 
                                BUF_BLOCK_REMOVE_HASH. */
2580
 
                                ut_ad(page_get_space_id(page_align(ptr))
2581
 
                                      == 0xffffffff);
2582
 
                                ut_ad(page_get_page_no(page_align(ptr))
2583
 
                                      == 0xffffffff);
2584
 
                                break;
2585
 
                        case BUF_BLOCK_FILE_PAGE:
2586
 
                                ut_ad(block->page.space
2587
 
                                      == page_get_space_id(page_align(ptr)));
2588
 
                                ut_ad(block->page.offset
2589
 
                                      == page_get_page_no(page_align(ptr)));
2590
 
                                break;
2591
 
                        }
2592
 
 
2593
 
                        mutex_exit(&block->mutex);
2594
 
#endif /* UNIV_DEBUG */
2595
 
 
2596
 
                        return(block);
2597
 
                }
2598
 
        }
2599
 
 
2600
 
        return(NULL);
2601
 
}
2602
 
 
2603
 
/*******************************************************************//**
2604
 
Gets the block to whose frame the pointer is pointing to.
2605
 
@return pointer to block, never NULL */
2606
 
UNIV_INTERN
2607
 
buf_block_t*
2608
 
buf_block_align(
2609
 
/*============*/
2610
 
        const byte*     ptr)    /*!< in: pointer to a frame */
2611
 
{
2612
 
        ulint           i;
2613
 
 
2614
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
2615
 
                buf_block_t*    block;
2616
 
 
2617
 
                block = buf_block_align_instance(
2618
 
                        buf_pool_from_array(i), ptr);
2619
 
                if (block) {
2620
 
                        return(block);
2621
 
                }
2622
 
        }
2623
 
 
2624
 
        /* The block should always be found. */
2625
 
        ut_error;
2626
 
        return(NULL);
2627
 
}
2628
 
 
2629
 
/********************************************************************//**
2630
 
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.
2633
 
@return TRUE if ptr belongs to a buf_block_t struct */
 
1752
/************************************************************************
 
1753
Find out if a buffer block was created by buf_chunk_init(). */
2634
1754
static
2635
1755
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 */
 
1756
buf_block_is_uncompressed(
 
1757
/*======================*/
 
1758
                                        /* out: TRUE if "block" has
 
1759
                                        been added to buf_pool->free
 
1760
                                        by buf_chunk_init() */
 
1761
        const buf_block_t*      block)  /* in: pointer to block,
 
1762
                                        not dereferenced */
2640
1763
{
2641
1764
        const buf_chunk_t*              chunk   = buf_pool->chunks;
2642
1765
        const buf_chunk_t* const        echunk  = chunk + buf_pool->n_chunks;
2643
1766
 
2644
 
        /* TODO: protect buf_pool->chunks with a mutex (it will
2645
 
        currently remain constant after buf_pool_init()) */
 
1767
        ut_ad(buf_pool_mutex_own());
 
1768
 
 
1769
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
 
1770
                /* The pointer should be aligned. */
 
1771
                return(FALSE);
 
1772
        }
 
1773
 
2646
1774
        while (chunk < echunk) {
2647
 
                if (ptr >= (void *)chunk->blocks
2648
 
                    && ptr < (void *)(chunk->blocks + chunk->size)) {
 
1775
                if (block >= chunk->blocks
 
1776
                    && block < chunk->blocks + chunk->size) {
2649
1777
 
2650
1778
                        return(TRUE);
2651
1779
                }
2656
1784
        return(FALSE);
2657
1785
}
2658
1786
 
2659
 
/********************************************************************//**
2660
 
Find out if a pointer belongs to a buf_block_t. It can be a pointer to
2661
 
the buf_block_t itself or a member of it
2662
 
@return TRUE if ptr belongs to a buf_block_t struct */
2663
 
UNIV_INTERN
2664
 
ibool
2665
 
buf_pointer_is_block_field(
2666
 
/*=======================*/
2667
 
        const void*     ptr)    /*!< in: pointer not dereferenced */
2668
 
{
2669
 
        ulint   i;
2670
 
 
2671
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
2672
 
                ibool   found;
2673
 
 
2674
 
                found = buf_pointer_is_block_field_instance(
2675
 
                        buf_pool_from_array(i), ptr);
2676
 
                if (found) {
2677
 
                        return(TRUE);
2678
 
                }
2679
 
        }
2680
 
 
2681
 
        return(FALSE);
2682
 
}
2683
 
 
2684
 
/********************************************************************//**
2685
 
Find out if a buffer block was created by buf_chunk_init().
2686
 
@return TRUE if "block" has been added to buf_pool->free by buf_chunk_init() */
2687
 
static
2688
 
ibool
2689
 
buf_block_is_uncompressed(
2690
 
/*======================*/
2691
 
        buf_pool_t*             buf_pool,       /*!< in: buffer pool instance */
2692
 
        const buf_block_t*      block)          /*!< in: pointer to block,
2693
 
                                                not dereferenced */
2694
 
{
2695
 
        ut_ad(buf_pool_mutex_own(buf_pool));
2696
 
 
2697
 
        if (UNIV_UNLIKELY((((ulint) block) % sizeof *block) != 0)) {
2698
 
                /* The pointer should be aligned. */
2699
 
                return(FALSE);
2700
 
        }
2701
 
 
2702
 
        return(buf_pointer_is_block_field_instance(buf_pool, (void *)block));
2703
 
}
2704
 
 
2705
 
/********************************************************************//**
2706
 
This is the general function used to get access to a database page.
2707
 
@return pointer to the block or NULL */
 
1787
/************************************************************************
 
1788
This is the general function used to get access to a database page. */
2708
1789
UNIV_INTERN
2709
1790
buf_block_t*
2710
1791
buf_page_get_gen(
2711
1792
/*=============*/
2712
 
        ulint           space,  /*!< in: space id */
2713
 
        ulint           zip_size,/*!< in: compressed page size in bytes
 
1793
                                /* out: pointer to the block or NULL */
 
1794
        ulint           space,  /* in: space id */
 
1795
        ulint           zip_size,/* in: compressed page size in bytes
2714
1796
                                or 0 for uncompressed pages */
2715
 
        ulint           offset, /*!< in: page number */
2716
 
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
2717
 
        buf_block_t*    guess,  /*!< in: guessed block or NULL */
2718
 
        ulint           mode,   /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
2719
 
                                BUF_GET_NO_LATCH, or
2720
 
                                BUF_GET_IF_IN_POOL_OR_WATCH */
2721
 
        const char*     file,   /*!< in: file name */
2722
 
        ulint           line,   /*!< in: line where called */
2723
 
        mtr_t*          mtr)    /*!< in: mini-transaction */
 
1797
        ulint           offset, /* in: page number */
 
1798
        ulint           rw_latch,/* in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
 
1799
        buf_block_t*    guess,  /* in: guessed block or NULL */
 
1800
        ulint           mode,   /* in: BUF_GET, BUF_GET_IF_IN_POOL,
 
1801
                                BUF_GET_NO_LATCH, BUF_GET_NOWAIT */
 
1802
        const char*     file,   /* in: file name */
 
1803
        ulint           line,   /* in: line where called */
 
1804
        mtr_t*          mtr)    /* in: mini-transaction */
2724
1805
{
2725
1806
        buf_block_t*    block;
2726
 
        ulint           fold;
2727
 
        unsigned        access_time;
 
1807
        ibool           accessed;
2728
1808
        ulint           fix_type;
2729
1809
        ibool           must_read;
2730
 
        ulint           retries = 0;
2731
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
2732
1810
 
2733
1811
        ut_ad(mtr);
2734
 
        ut_ad(mtr->state == MTR_ACTIVE);
2735
1812
        ut_ad((rw_latch == RW_S_LATCH)
2736
1813
              || (rw_latch == RW_X_LATCH)
2737
1814
              || (rw_latch == RW_NO_LATCH));
2738
1815
        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);
 
1816
        ut_ad((mode == BUF_GET) || (mode == BUF_GET_IF_IN_POOL)
 
1817
              || (mode == BUF_GET_NO_LATCH) || (mode == BUF_GET_NOWAIT));
2743
1818
        ut_ad(zip_size == fil_space_get_zip_size(space));
2744
 
        ut_ad(ut_is_2pow(zip_size));
2745
1819
#ifndef UNIV_LOG_DEBUG
2746
 
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset, NULL));
 
1820
        ut_ad(!ibuf_inside() || ibuf_page(space, zip_size, offset));
2747
1821
#endif
2748
 
        buf_pool->stat.n_page_gets++;
2749
 
        fold = buf_page_address_fold(space, offset);
 
1822
        buf_pool->n_page_gets++;
2750
1823
loop:
2751
1824
        block = guess;
2752
 
        buf_pool_mutex_enter(buf_pool);
 
1825
        buf_pool_mutex_enter();
2753
1826
 
2754
1827
        if (block) {
2755
1828
                /* If the guess is a compressed page descriptor that
2760
1833
                the guess may be pointing to a buffer pool chunk that
2761
1834
                has been released when resizing the buffer pool. */
2762
1835
 
2763
 
                if (!buf_block_is_uncompressed(buf_pool, block)
 
1836
                if (!buf_block_is_uncompressed(block)
2764
1837
                    || offset != block->page.offset
2765
1838
                    || space != block->page.space
2766
1839
                    || buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
2773
1846
        }
2774
1847
 
2775
1848
        if (block == NULL) {
2776
 
                block = (buf_block_t*) buf_page_hash_get_low(
2777
 
                        buf_pool, space, offset, fold);
 
1849
                block = (buf_block_t*) buf_page_hash_get(space, offset);
2778
1850
        }
2779
1851
 
2780
1852
loop2:
2781
 
        if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
2782
 
                block = NULL;
2783
 
        }
2784
 
 
2785
1853
        if (block == NULL) {
2786
1854
                /* Page not in buf_pool: needs to be read from file */
2787
1855
 
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) {
 
1856
                buf_pool_mutex_exit();
 
1857
 
 
1858
                if (mode == BUF_GET_IF_IN_POOL) {
2802
1859
 
2803
1860
                        return(NULL);
2804
1861
                }
2805
1862
 
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
 
                }
 
1863
                buf_read_page(space, zip_size, offset);
2829
1864
 
2830
1865
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
2831
1866
                ut_a(++buf_dbg_counter % 37 || buf_validate());
2833
1868
                goto loop;
2834
1869
        }
2835
1870
 
2836
 
got_block:
2837
1871
        ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
2838
1872
 
2839
1873
        must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
2840
1874
 
2841
1875
        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);
 
1876
                /* The page is only being read to buffer */
 
1877
                buf_pool_mutex_exit();
2847
1878
 
2848
1879
                return(NULL);
2849
1880
        }
2858
1889
        case BUF_BLOCK_ZIP_PAGE:
2859
1890
        case BUF_BLOCK_ZIP_DIRTY:
2860
1891
                bpage = &block->page;
2861
 
                /* Protect bpage->buf_fix_count. */
2862
 
                mutex_enter(&buf_pool->zip_mutex);
2863
1892
 
2864
1893
                if (bpage->buf_fix_count
2865
1894
                    || buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
2866
1895
                        /* This condition often occurs when the buffer
2867
1896
                        is not buffer-fixed, but I/O-fixed by
2868
1897
                        buf_page_init_for_read(). */
2869
 
                        mutex_exit(&buf_pool->zip_mutex);
2870
1898
wait_until_unfixed:
2871
1899
                        /* The block is buffer-fixed or I/O-fixed.
2872
1900
                        Try again later. */
2873
 
                        buf_pool_mutex_exit(buf_pool);
 
1901
                        buf_pool_mutex_exit();
2874
1902
                        os_thread_sleep(WAIT_FOR_READ);
2875
 
  
 
1903
 
2876
1904
                        goto loop;
2877
1905
                }
2878
1906
 
2879
1907
                /* Allocate an uncompressed page. */
2880
 
                buf_pool_mutex_exit(buf_pool);
2881
 
                mutex_exit(&buf_pool->zip_mutex);
 
1908
                buf_pool_mutex_exit();
2882
1909
 
2883
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
1910
                block = buf_LRU_get_free_block(0);
2884
1911
                ut_a(block);
2885
1912
 
2886
 
                buf_pool_mutex_enter(buf_pool);
 
1913
                buf_pool_mutex_enter();
2887
1914
                mutex_enter(&block->mutex);
2888
1915
 
2889
1916
                {
2890
 
                        buf_page_t*     hash_bpage;
2891
 
 
2892
 
                        hash_bpage = buf_page_hash_get_low(
2893
 
                                buf_pool, space, offset, fold);
 
1917
                        buf_page_t*     hash_bpage
 
1918
                                = buf_page_hash_get(space, offset);
2894
1919
 
2895
1920
                        if (UNIV_UNLIKELY(bpage != hash_bpage)) {
2896
1921
                                /* The buf_pool->page_hash was modified
2897
 
                                while buf_pool->mutex was released.
 
1922
                                while buf_pool_mutex was released.
2898
1923
                                Free the block that was allocated. */
2899
1924
 
2900
1925
                                buf_LRU_block_free_non_file_page(block);
2910
1935
                     || buf_page_get_io_fix(bpage) != BUF_IO_NONE)) {
2911
1936
 
2912
1937
                        /* The block was buffer-fixed or I/O-fixed
2913
 
                        while buf_pool->mutex was not held by this thread.
 
1938
                        while buf_pool_mutex was not held by this thread.
2914
1939
                        Free the block that was allocated and try again.
2915
1940
                        This should be extremely unlikely. */
2916
1941
 
2923
1948
                /* Move the compressed page from bpage to block,
2924
1949
                and uncompress it. */
2925
1950
 
2926
 
                mutex_enter(&buf_pool->zip_mutex);
 
1951
                mutex_enter(&buf_pool_zip_mutex);
2927
1952
 
2928
1953
                buf_relocate(bpage, &block->page);
2929
1954
                buf_block_init_low(block);
2939
1964
                        ut_ad(!block->page.in_flush_list);
2940
1965
                } else {
2941
1966
                        /* Relocate buf_pool->flush_list. */
2942
 
                        buf_flush_relocate_on_flush_list(bpage,
2943
 
                                                         &block->page);
 
1967
                        buf_page_t*     b;
 
1968
 
 
1969
                        b = UT_LIST_GET_PREV(list, &block->page);
 
1970
                        ut_ad(block->page.in_flush_list);
 
1971
                        UT_LIST_REMOVE(list, buf_pool->flush_list,
 
1972
                                       &block->page);
 
1973
 
 
1974
                        if (b) {
 
1975
                                UT_LIST_INSERT_AFTER(
 
1976
                                        list, buf_pool->flush_list, b,
 
1977
                                        &block->page);
 
1978
                        } else {
 
1979
                                UT_LIST_ADD_FIRST(
 
1980
                                        list, buf_pool->flush_list,
 
1981
                                        &block->page);
 
1982
                        }
2944
1983
                }
2945
1984
 
2946
1985
                /* Buffer-fix, I/O-fix, and X-latch the block
2953
1992
 
2954
1993
                block->page.buf_fix_count = 1;
2955
1994
                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
 
 
2960
 
                mutex_exit(&block->mutex);
2961
 
                mutex_exit(&buf_pool->zip_mutex);
2962
1995
                buf_pool->n_pend_unzip++;
2963
 
 
2964
 
                buf_buddy_free(buf_pool, bpage, sizeof *bpage);
2965
 
 
2966
 
                buf_pool_mutex_exit(buf_pool);
 
1996
                rw_lock_x_lock(&block->lock);
 
1997
                mutex_exit(&block->mutex);
 
1998
                mutex_exit(&buf_pool_zip_mutex);
 
1999
 
 
2000
                buf_buddy_free(bpage, sizeof *bpage);
 
2001
 
 
2002
                buf_pool_mutex_exit();
2967
2003
 
2968
2004
                /* Decompress the page and apply buffered operations
2969
 
                while not holding buf_pool->mutex or block->mutex. */
 
2005
                while not holding buf_pool_mutex or block->mutex. */
2970
2006
                success = buf_zip_decompress(block, srv_use_checksums);
2971
 
                ut_a(success);
2972
2007
 
2973
 
                if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
 
2008
                if (UNIV_LIKELY(success)) {
2974
2009
                        ibuf_merge_or_delete_for_page(block, space, offset,
2975
2010
                                                      zip_size, TRUE);
2976
2011
                }
2977
2012
 
2978
2013
                /* Unfix and unlatch the block. */
2979
 
                buf_pool_mutex_enter(buf_pool);
 
2014
                buf_pool_mutex_enter();
2980
2015
                mutex_enter(&block->mutex);
 
2016
                buf_pool->n_pend_unzip--;
2981
2017
                block->page.buf_fix_count--;
2982
2018
                buf_block_set_io_fix(block, BUF_IO_NONE);
2983
2019
                mutex_exit(&block->mutex);
2984
 
                buf_pool->n_pend_unzip--;
2985
2020
                rw_lock_x_unlock(&block->lock);
2986
2021
 
 
2022
                if (UNIV_UNLIKELY(!success)) {
 
2023
 
 
2024
                        buf_pool_mutex_exit();
 
2025
                        return(NULL);
 
2026
                }
 
2027
 
2987
2028
                break;
2988
2029
 
2989
2030
        case BUF_BLOCK_ZIP_FREE:
2998
2039
        ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
2999
2040
 
3000
2041
        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
2042
        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
2043
 
3048
2044
        buf_block_buf_fix_inc(block, file, line);
 
2045
        buf_pool_mutex_exit();
 
2046
 
 
2047
        /* Check if this is the first access to the page */
 
2048
 
 
2049
        accessed = buf_page_is_accessed(&block->page);
 
2050
 
 
2051
        buf_page_set_accessed(&block->page, TRUE);
3049
2052
 
3050
2053
        mutex_exit(&block->mutex);
3051
2054
 
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);
 
2055
        buf_block_make_young(&block->page);
3059
2056
 
3060
2057
#ifdef UNIV_DEBUG_FILE_ACCESSES
3061
2058
        ut_a(!block->page.file_page_was_freed);
3067
2064
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3068
2065
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
3069
2066
 
3070
 
        switch (rw_latch) {
3071
 
        case RW_NO_LATCH:
 
2067
        if (mode == BUF_GET_NOWAIT) {
 
2068
                ibool   success;
 
2069
 
 
2070
                if (rw_latch == RW_S_LATCH) {
 
2071
                        success = rw_lock_s_lock_func_nowait(&(block->lock),
 
2072
                                                             file, line);
 
2073
                        fix_type = MTR_MEMO_PAGE_S_FIX;
 
2074
                } else {
 
2075
                        ut_ad(rw_latch == RW_X_LATCH);
 
2076
                        success = rw_lock_x_lock_func_nowait(&(block->lock),
 
2077
                                                             file, line);
 
2078
                        fix_type = MTR_MEMO_PAGE_X_FIX;
 
2079
                }
 
2080
 
 
2081
                if (!success) {
 
2082
                        mutex_enter(&block->mutex);
 
2083
                        buf_block_buf_fix_dec(block);
 
2084
                        mutex_exit(&block->mutex);
 
2085
 
 
2086
                        return(NULL);
 
2087
                }
 
2088
        } else if (rw_latch == RW_NO_LATCH) {
 
2089
 
3072
2090
                if (must_read) {
3073
2091
                        /* Let us wait until the read operation
3074
2092
                        completes */
3090
2108
                }
3091
2109
 
3092
2110
                fix_type = MTR_MEMO_BUF_FIX;
3093
 
                break;
 
2111
        } else if (rw_latch == RW_S_LATCH) {
3094
2112
 
3095
 
        case RW_S_LATCH:
3096
2113
                rw_lock_s_lock_func(&(block->lock), 0, file, line);
3097
2114
 
3098
2115
                fix_type = MTR_MEMO_PAGE_S_FIX;
3099
 
                break;
3100
 
 
3101
 
        default:
3102
 
                ut_ad(rw_latch == RW_X_LATCH);
 
2116
        } else {
3103
2117
                rw_lock_x_lock_func(&(block->lock), 0, file, line);
3104
2118
 
3105
2119
                fix_type = MTR_MEMO_PAGE_X_FIX;
3106
 
                break;
3107
2120
        }
3108
2121
 
3109
2122
        mtr_memo_push(mtr, block, fix_type);
3110
2123
 
3111
 
        if (!access_time) {
 
2124
        if (!accessed) {
3112
2125
                /* In the case of a first access, try to apply linear
3113
2126
                read-ahead */
3114
2127
 
3122
2135
        return(block);
3123
2136
}
3124
2137
 
3125
 
/********************************************************************//**
 
2138
/************************************************************************
3126
2139
This is the general function used to get optimistic access to a database
3127
 
page.
3128
 
@return TRUE if success */
 
2140
page. */
3129
2141
UNIV_INTERN
3130
2142
ibool
3131
 
buf_page_optimistic_get(
3132
 
/*====================*/
3133
 
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
3134
 
        buf_block_t*    block,  /*!< in: guessed buffer block */
3135
 
        ib_uint64_t     modify_clock,/*!< in: modify clock value if mode is
 
2143
buf_page_optimistic_get_func(
 
2144
/*=========================*/
 
2145
                                /* out: TRUE if success */
 
2146
        ulint           rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */
 
2147
        buf_block_t*    block,  /* in: guessed buffer block */
 
2148
        ib_uint64_t     modify_clock,/* in: modify clock value if mode is
3136
2149
                                ..._GUESS_ON_CLOCK */
3137
 
        const char*     file,   /*!< in: file name */
3138
 
        ulint           line,   /*!< in: line where called */
3139
 
        mtr_t*          mtr)    /*!< in: mini-transaction */
 
2150
        const char*     file,   /* in: file name */
 
2151
        ulint           line,   /* in: line where called */
 
2152
        mtr_t*          mtr)    /* in: mini-transaction */
3140
2153
{
3141
 
        buf_pool_t*     buf_pool;
3142
 
        unsigned        access_time;
 
2154
        ibool           accessed;
3143
2155
        ibool           success;
3144
2156
        ulint           fix_type;
3145
2157
 
3146
 
        ut_ad(block);
3147
 
        ut_ad(mtr);
3148
 
        ut_ad(mtr->state == MTR_ACTIVE);
 
2158
        ut_ad(mtr && block);
3149
2159
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3150
2160
 
3151
2161
        mutex_enter(&block->mutex);
3158
2168
        }
3159
2169
 
3160
2170
        buf_block_buf_fix_inc(block, file, line);
 
2171
        accessed = buf_page_is_accessed(&block->page);
 
2172
        buf_page_set_accessed(&block->page, TRUE);
3161
2173
 
3162
2174
        mutex_exit(&block->mutex);
3163
2175
 
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. */
 
2176
        buf_block_make_young(&block->page);
3168
2177
 
3169
 
        access_time = buf_page_is_accessed(&block->page);
3170
 
        buf_page_set_accessed_make_young(&block->page, access_time);
 
2178
        /* Check if this is the first access to the page */
3171
2179
 
3172
2180
        ut_ad(!ibuf_inside()
3173
2181
              || ibuf_page(buf_block_get_space(block),
3174
2182
                           buf_block_get_zip_size(block),
3175
 
                           buf_block_get_page_no(block), NULL));
 
2183
                           buf_block_get_page_no(block)));
3176
2184
 
3177
2185
        if (rw_latch == RW_S_LATCH) {
3178
 
                success = rw_lock_s_lock_nowait(&(block->lock),
3179
 
                                                file, line);
 
2186
                success = rw_lock_s_lock_func_nowait(&(block->lock),
 
2187
                                                     file, line);
3180
2188
                fix_type = MTR_MEMO_PAGE_S_FIX;
3181
2189
        } else {
3182
2190
                success = rw_lock_x_lock_func_nowait(&(block->lock),
3219
2227
#ifdef UNIV_DEBUG_FILE_ACCESSES
3220
2228
        ut_a(block->page.file_page_was_freed == FALSE);
3221
2229
#endif
3222
 
        if (UNIV_UNLIKELY(!access_time)) {
 
2230
        if (UNIV_UNLIKELY(!accessed)) {
3223
2231
                /* In the case of a first access, try to apply linear
3224
2232
                read-ahead */
3225
2233
 
3232
2240
        ut_a(ibuf_count_get(buf_block_get_space(block),
3233
2241
                            buf_block_get_page_no(block)) == 0);
3234
2242
#endif
3235
 
        buf_pool = buf_pool_from_block(block);
3236
 
        buf_pool->stat.n_page_gets++;
 
2243
        buf_pool->n_page_gets++;
3237
2244
 
3238
2245
        return(TRUE);
3239
2246
}
3240
2247
 
3241
 
/********************************************************************//**
 
2248
/************************************************************************
3242
2249
This is used to get access to a known database page, when no waiting can be
3243
2250
done. For example, if a search in an adaptive hash index leads us to this
3244
 
frame.
3245
 
@return TRUE if success */
 
2251
frame. */
3246
2252
UNIV_INTERN
3247
2253
ibool
3248
2254
buf_page_get_known_nowait(
3249
2255
/*======================*/
3250
 
        ulint           rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
3251
 
        buf_block_t*    block,  /*!< in: the known page */
3252
 
        ulint           mode,   /*!< in: BUF_MAKE_YOUNG or BUF_KEEP_OLD */
3253
 
        const char*     file,   /*!< in: file name */
3254
 
        ulint           line,   /*!< in: line where called */
3255
 
        mtr_t*          mtr)    /*!< in: mini-transaction */
 
2256
                                /* out: TRUE if success */
 
2257
        ulint           rw_latch,/* in: RW_S_LATCH, RW_X_LATCH */
 
2258
        buf_block_t*    block,  /* in: the known page */
 
2259
        ulint           mode,   /* in: BUF_MAKE_YOUNG or BUF_KEEP_OLD */
 
2260
        const char*     file,   /* in: file name */
 
2261
        ulint           line,   /* in: line where called */
 
2262
        mtr_t*          mtr)    /* in: mini-transaction */
3256
2263
{
3257
 
        buf_pool_t*     buf_pool;
3258
2264
        ibool           success;
3259
2265
        ulint           fix_type;
3260
2266
 
3261
2267
        ut_ad(mtr);
3262
 
        ut_ad(mtr->state == MTR_ACTIVE);
3263
2268
        ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
3264
2269
 
3265
2270
        mutex_enter(&block->mutex);
3283
2288
 
3284
2289
        mutex_exit(&block->mutex);
3285
2290
 
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);
 
2291
        if (mode == BUF_MAKE_YOUNG) {
 
2292
                buf_block_make_young(&block->page);
3302
2293
        }
3303
2294
 
3304
2295
        ut_ad(!ibuf_inside() || (mode == BUF_KEEP_OLD));
3305
2296
 
3306
2297
        if (rw_latch == RW_S_LATCH) {
3307
 
                success = rw_lock_s_lock_nowait(&(block->lock),
3308
 
                                                file, line);
 
2298
                success = rw_lock_s_lock_func_nowait(&(block->lock),
 
2299
                                                     file, line);
3309
2300
                fix_type = MTR_MEMO_PAGE_S_FIX;
3310
2301
        } else {
3311
2302
                success = rw_lock_x_lock_func_nowait(&(block->lock),
3337
2328
             || (ibuf_count_get(buf_block_get_space(block),
3338
2329
                                buf_block_get_page_no(block)) == 0));
3339
2330
#endif
3340
 
        buf_pool->stat.n_page_gets++;
 
2331
        buf_pool->n_page_gets++;
3341
2332
 
3342
2333
        return(TRUE);
3343
2334
}
3344
2335
 
3345
 
/*******************************************************************//**
 
2336
/***********************************************************************
3346
2337
Given a tablespace id and page number tries to get that page. If the
3347
2338
page is not in the buffer pool it is not loaded and NULL is returned.
3348
 
Suitable for using when holding the kernel mutex.
3349
 
@return pointer to a page or NULL */
 
2339
Suitable for using when holding the kernel mutex. */
3350
2340
UNIV_INTERN
3351
2341
const buf_block_t*
3352
2342
buf_page_try_get_func(
3353
2343
/*==================*/
3354
 
        ulint           space_id,/*!< in: tablespace id */
3355
 
        ulint           page_no,/*!< in: page number */
3356
 
        const char*     file,   /*!< in: file name */
3357
 
        ulint           line,   /*!< in: line where called */
3358
 
        mtr_t*          mtr)    /*!< in: mini-transaction */
 
2344
                                /* out: pointer to a page or NULL */
 
2345
        ulint           space_id,/* in: tablespace id */
 
2346
        ulint           page_no,/* in: page number */
 
2347
        const char*     file,   /* in: file name */
 
2348
        ulint           line,   /* in: line where called */
 
2349
        mtr_t*          mtr)    /* in: mini-transaction */
3359
2350
{
3360
2351
        buf_block_t*    block;
3361
2352
        ibool           success;
3362
2353
        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);
 
2354
 
 
2355
        buf_pool_mutex_enter();
 
2356
        block = buf_block_hash_get(space_id, page_no);
 
2357
 
 
2358
        if (!block) {
 
2359
                buf_pool_mutex_exit();
3373
2360
                return(NULL);
3374
2361
        }
3375
2362
 
3376
 
        ut_ad(!buf_pool_watch_is_sentinel(buf_pool, &block->page));
3377
 
 
3378
2363
        mutex_enter(&block->mutex);
3379
 
        buf_pool_mutex_exit(buf_pool);
 
2364
        buf_pool_mutex_exit();
3380
2365
 
3381
2366
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3382
2367
        ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
3388
2373
        mutex_exit(&block->mutex);
3389
2374
 
3390
2375
        fix_type = MTR_MEMO_PAGE_S_FIX;
3391
 
        success = rw_lock_s_lock_nowait(&block->lock, file, line);
 
2376
        success = rw_lock_s_lock_func_nowait(&block->lock, file, line);
3392
2377
 
3393
2378
        if (!success) {
3394
2379
                /* Let us try to get an X-latch. If the current thread
3419
2404
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3420
2405
        buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
3421
2406
 
3422
 
        buf_pool->stat.n_page_gets++;
3423
 
 
3424
 
#ifdef UNIV_IBUF_COUNT_DEBUG
3425
 
        ut_a(ibuf_count_get(buf_block_get_space(block),
3426
 
                            buf_block_get_page_no(block)) == 0);
3427
 
#endif
 
2407
        buf_pool->n_page_gets++;
3428
2408
 
3429
2409
        return(block);
3430
2410
}
3431
2411
 
3432
 
/********************************************************************//**
 
2412
/************************************************************************
3433
2413
Initialize some fields of a control block. */
3434
2414
UNIV_INLINE
3435
2415
void
3436
2416
buf_page_init_low(
3437
2417
/*==============*/
3438
 
        buf_page_t*     bpage)  /*!< in: block to init */
 
2418
        buf_page_t*     bpage)  /* in: block to init */
3439
2419
{
3440
2420
        bpage->flush_type = BUF_FLUSH_LRU;
 
2421
        bpage->accessed = FALSE;
3441
2422
        bpage->io_fix = BUF_IO_NONE;
3442
2423
        bpage->buf_fix_count = 0;
3443
2424
        bpage->freed_page_clock = 0;
3444
 
        bpage->access_time = 0;
3445
2425
        bpage->newest_modification = 0;
3446
2426
        bpage->oldest_modification = 0;
3447
2427
        HASH_INVALIDATE(bpage, hash);
3450
2430
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3451
2431
}
3452
2432
 
3453
 
/********************************************************************//**
 
2433
#ifdef UNIV_HOTBACKUP
 
2434
/************************************************************************
 
2435
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
 
2436
UNIV_INTERN
 
2437
void
 
2438
buf_page_init_for_backup_restore(
 
2439
/*=============================*/
 
2440
        ulint           space,  /* in: space id */
 
2441
        ulint           offset, /* in: offset of the page within space
 
2442
                                in units of a page */
 
2443
        ulint           zip_size,/* in: compressed page size in bytes
 
2444
                                or 0 for uncompressed pages */
 
2445
        buf_block_t*    block)  /* in: block to init */
 
2446
{
 
2447
        buf_block_init_low(block);
 
2448
 
 
2449
        block->lock_hash_val    = 0;
 
2450
 
 
2451
        buf_page_init_low(&block->page);
 
2452
        block->page.state       = BUF_BLOCK_FILE_PAGE;
 
2453
        block->page.space       = space;
 
2454
        block->page.offset      = offset;
 
2455
 
 
2456
        page_zip_des_init(&block->page.zip);
 
2457
 
 
2458
        /* We assume that block->page.data has been allocated
 
2459
        with zip_size == UNIV_PAGE_SIZE. */
 
2460
        ut_ad(zip_size <= UNIV_PAGE_SIZE);
 
2461
        ut_ad(ut_is_2pow(zip_size));
 
2462
        page_zip_set_size(&block->page.zip, zip_size);
 
2463
}
 
2464
#endif /* UNIV_HOTBACKUP */
 
2465
 
 
2466
/************************************************************************
3454
2467
Inits a page to the buffer buf_pool. */
3455
2468
static
3456
2469
void
3457
2470
buf_page_init(
3458
2471
/*==========*/
3459
 
        ulint           space,  /*!< in: space id */
3460
 
        ulint           offset, /*!< in: offset of the page within space
 
2472
        ulint           space,  /* in: space id */
 
2473
        ulint           offset, /* in: offset of the page within space
3461
2474
                                in units of a page */
3462
 
        ulint           fold,   /*!< in: buf_page_address_fold(space,offset) */
3463
 
        buf_block_t*    block)  /*!< in: block to init */
 
2475
        buf_block_t*    block)  /* in: block to init */
3464
2476
{
3465
2477
        buf_page_t*     hash_page;
3466
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3467
2478
 
3468
 
        ut_ad(buf_pool_mutex_own(buf_pool));
 
2479
        ut_ad(buf_pool_mutex_own());
3469
2480
        ut_ad(mutex_own(&(block->mutex)));
3470
2481
        ut_a(buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE);
3471
2482
 
3483
2494
 
3484
2495
        buf_block_init_low(block);
3485
2496
 
3486
 
        block->lock_hash_val = lock_rec_hash(space, offset);
3487
 
 
3488
 
        buf_page_init_low(&block->page);
 
2497
        block->lock_hash_val    = lock_rec_hash(space, offset);
3489
2498
 
3490
2499
        /* Insert into the hash table of file pages */
3491
2500
 
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 {
 
2501
        hash_page = buf_page_hash_get(space, offset);
 
2502
 
 
2503
        if (UNIV_LIKELY_NULL(hash_page)) {
3503
2504
                fprintf(stderr,
3504
2505
                        "InnoDB: Error: page %lu %lu already found"
3505
2506
                        " in the hash table: %p, %p\n",
3508
2509
                        (const void*) hash_page, (const void*) block);
3509
2510
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
3510
2511
                mutex_exit(&block->mutex);
3511
 
                buf_pool_mutex_exit(buf_pool);
 
2512
                buf_pool_mutex_exit();
3512
2513
                buf_print();
3513
2514
                buf_LRU_print();
3514
2515
                buf_validate();
3517
2518
                ut_error;
3518
2519
        }
3519
2520
 
 
2521
        buf_page_init_low(&block->page);
 
2522
 
3520
2523
        ut_ad(!block->page.in_zip_hash);
3521
2524
        ut_ad(!block->page.in_page_hash);
3522
2525
        ut_d(block->page.in_page_hash = TRUE);
3523
2526
        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
3524
 
                    fold, &block->page);
 
2527
                    buf_page_address_fold(space, offset), &block->page);
3525
2528
}
3526
2529
 
3527
 
/********************************************************************//**
 
2530
/************************************************************************
3528
2531
Function which inits a page for read to the buffer buf_pool. If the page is
3529
2532
(1) already in buf_pool, or
3530
2533
(2) if we specify to read only ibuf pages and the page is not an ibuf page, or
3532
2535
then this function does nothing.
3533
2536
Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock
3534
2537
on the buffer frame. The io-handler must take care that the flag is cleared
3535
 
and the lock released later.
3536
 
@return pointer to the block or NULL */
 
2538
and the lock released later. */
3537
2539
UNIV_INTERN
3538
2540
buf_page_t*
3539
2541
buf_page_init_for_read(
3540
2542
/*===================*/
3541
 
        ulint*          err,    /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED */
3542
 
        ulint           mode,   /*!< in: BUF_READ_IBUF_PAGES_ONLY, ... */
3543
 
        ulint           space,  /*!< in: space id */
3544
 
        ulint           zip_size,/*!< in: compressed page size, or 0 */
3545
 
        ibool           unzip,  /*!< in: TRUE=request uncompressed page */
3546
 
        ib_int64_t      tablespace_version,
3547
 
                                /*!< in: prevents reading from a wrong
 
2543
                                /* out: pointer to the block or NULL */
 
2544
        ulint*          err,    /* out: DB_SUCCESS or DB_TABLESPACE_DELETED */
 
2545
        ulint           mode,   /* in: BUF_READ_IBUF_PAGES_ONLY, ... */
 
2546
        ulint           space,  /* in: space id */
 
2547
        ulint           zip_size,/* in: compressed page size, or 0 */
 
2548
        ibool           unzip,  /* in: TRUE=request uncompressed page */
 
2549
        ib_int64_t      tablespace_version,/* in: prevents reading from a wrong
3548
2550
                                version of the tablespace in case we have done
3549
2551
                                DISCARD + IMPORT */
3550
 
        ulint           offset) /*!< in: page number */
 
2552
        ulint           offset) /* in: page number */
3551
2553
{
3552
2554
        buf_block_t*    block;
3553
 
        buf_page_t*     bpage   = NULL;
3554
 
        buf_page_t*     watch_page;
 
2555
        buf_page_t*     bpage;
3555
2556
        mtr_t           mtr;
3556
 
        ulint           fold;
3557
2557
        ibool           lru     = FALSE;
3558
2558
        void*           data;
3559
 
        buf_pool_t*     buf_pool = buf_pool_get(space, offset);
3560
2559
 
3561
2560
        ut_ad(buf_pool);
3562
2561
 
3570
2569
 
3571
2570
                mtr_start(&mtr);
3572
2571
 
3573
 
                if (!recv_no_ibuf_operations
3574
 
                    && !ibuf_page(space, zip_size, offset, &mtr)) {
 
2572
                if (!ibuf_page_low(space, zip_size, offset, &mtr)) {
3575
2573
 
3576
2574
                        mtr_commit(&mtr);
3577
2575
 
3585
2583
            && UNIV_LIKELY(!recv_recovery_is_on())) {
3586
2584
                block = NULL;
3587
2585
        } else {
3588
 
                block = buf_LRU_get_free_block(buf_pool, 0);
 
2586
                block = buf_LRU_get_free_block(0);
3589
2587
                ut_ad(block);
3590
 
                ut_ad(buf_pool_from_block(block) == buf_pool);
3591
2588
        }
3592
2589
 
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)) {
 
2590
        buf_pool_mutex_enter();
 
2591
 
 
2592
        if (buf_page_hash_get(space, offset)) {
3599
2593
                /* The page is already in the buffer pool. */
3600
 
                watch_page = NULL;
3601
2594
err_exit:
3602
2595
                if (block) {
3603
2596
                        mutex_enter(&block->mutex);
3605
2598
                        mutex_exit(&block->mutex);
3606
2599
                }
3607
2600
 
3608
 
                bpage = NULL;
3609
 
                goto func_exit;
 
2601
err_exit2:
 
2602
                buf_pool_mutex_exit();
 
2603
 
 
2604
                if (mode == BUF_READ_IBUF_PAGES_ONLY) {
 
2605
 
 
2606
                        mtr_commit(&mtr);
 
2607
                }
 
2608
 
 
2609
                return(NULL);
3610
2610
        }
3611
2611
 
3612
2612
        if (fil_tablespace_deleted_or_being_deleted_in_mem(
3621
2621
        if (block) {
3622
2622
                bpage = &block->page;
3623
2623
                mutex_enter(&block->mutex);
3624
 
 
3625
 
                ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
3626
 
 
3627
 
                buf_page_init(space, offset, fold, block);
 
2624
                buf_page_init(space, offset, block);
3628
2625
 
3629
2626
                /* The block must be put to the LRU list, to the old blocks */
3630
2627
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3644
2641
                if (UNIV_UNLIKELY(zip_size)) {
3645
2642
                        page_zip_set_size(&block->page.zip, zip_size);
3646
2643
 
3647
 
                        /* buf_pool->mutex may be released and
 
2644
                        /* buf_pool_mutex may be released and
3648
2645
                        reacquired by buf_buddy_alloc().  Thus, we
3649
2646
                        must release block->mutex in order not to
3650
2647
                        break the latching order in the reacquisition
3651
 
                        of buf_pool->mutex.  We also must defer this
 
2648
                        of buf_pool_mutex.  We also must defer this
3652
2649
                        operation until after the block descriptor has
3653
2650
                        been added to buf_pool->LRU and
3654
2651
                        buf_pool->page_hash. */
3655
2652
                        mutex_exit(&block->mutex);
3656
 
                        data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2653
                        data = buf_buddy_alloc(zip_size, &lru);
3657
2654
                        mutex_enter(&block->mutex);
3658
 
                        block->page.zip.data = static_cast<unsigned char *>(data);
 
2655
                        block->page.zip.data = data;
3659
2656
 
3660
2657
                        /* To maintain the invariant
3661
2658
                        block->in_unzip_LRU_list
3677
2674
                control block (bpage), in order to avoid the
3678
2675
                invocation of buf_buddy_relocate_block() on
3679
2676
                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);
 
2677
                data = buf_buddy_alloc(zip_size, &lru);
 
2678
                bpage = buf_buddy_alloc(sizeof *bpage, &lru);
3685
2679
 
3686
2680
                /* If buf_buddy_alloc() allocated storage from the LRU list,
3687
 
                it released and reacquired buf_pool->mutex.  Thus, we must
 
2681
                it released and reacquired buf_pool_mutex.  Thus, we must
3688
2682
                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
 
                        }
 
2683
                if (UNIV_UNLIKELY(lru)
 
2684
                    && UNIV_LIKELY_NULL(buf_page_hash_get(space, offset))) {
 
2685
 
 
2686
                        /* The block was added by some other thread. */
 
2687
                        buf_buddy_free(bpage, sizeof *bpage);
 
2688
                        buf_buddy_free(data, zip_size);
 
2689
                        goto err_exit2;
3706
2690
                }
3707
2691
 
3708
2692
                page_zip_des_init(&bpage->zip);
3709
2693
                page_zip_set_size(&bpage->zip, zip_size);
3710
 
                bpage->zip.data = static_cast<unsigned char *>(data);
 
2694
                bpage->zip.data = data;
3711
2695
 
3712
 
                mutex_enter(&buf_pool->zip_mutex);
 
2696
                mutex_enter(&buf_pool_zip_mutex);
3713
2697
                UNIV_MEM_DESC(bpage->zip.data,
3714
2698
                              page_zip_get_size(&bpage->zip), bpage);
3715
 
 
3716
2699
                buf_page_init_low(bpage);
3717
 
 
3718
2700
                bpage->state    = BUF_BLOCK_ZIP_PAGE;
3719
2701
                bpage->space    = space;
3720
2702
                bpage->offset   = offset;
3721
2703
 
3722
 
 
3723
2704
#ifdef UNIV_DEBUG
3724
2705
                bpage->in_page_hash = FALSE;
3725
2706
                bpage->in_zip_hash = FALSE;
3729
2710
#endif /* UNIV_DEBUG */
3730
2711
 
3731
2712
                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);
 
2713
                HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
 
2714
                            buf_page_address_fold(space, offset), bpage);
3744
2715
 
3745
2716
                /* The block must be put to the LRU list, to the old blocks */
3746
2717
                buf_LRU_add_block(bpage, TRUE/* to old blocks */);
3748
2719
 
3749
2720
                buf_page_set_io_fix(bpage, BUF_IO_READ);
3750
2721
 
3751
 
                mutex_exit(&buf_pool->zip_mutex);
 
2722
                mutex_exit(&buf_pool_zip_mutex);
3752
2723
        }
3753
2724
 
3754
2725
        buf_pool->n_pend_reads++;
3755
 
func_exit:
3756
 
        buf_pool_mutex_exit(buf_pool);
 
2726
        buf_pool_mutex_exit();
3757
2727
 
3758
2728
        if (mode == BUF_READ_IBUF_PAGES_ONLY) {
3759
2729
 
3760
2730
                mtr_commit(&mtr);
3761
2731
        }
3762
2732
 
3763
 
        ut_ad(!bpage || buf_page_in_file(bpage));
 
2733
        ut_ad(buf_page_in_file(bpage));
3764
2734
        return(bpage);
3765
2735
}
3766
2736
 
3767
 
/********************************************************************//**
 
2737
/************************************************************************
3768
2738
Initializes a page to the buffer buf_pool. The page is usually not read
3769
2739
from a file even if it cannot be found in the buffer buf_pool. This is one
3770
2740
of the functions which perform to a block a state transition NOT_USED =>
3771
 
FILE_PAGE (the other is buf_page_get_gen).
3772
 
@return pointer to the block, page bufferfixed */
 
2741
FILE_PAGE (the other is buf_page_get_gen). */
3773
2742
UNIV_INTERN
3774
2743
buf_block_t*
3775
2744
buf_page_create(
3776
2745
/*============*/
3777
 
        ulint   space,  /*!< in: space id */
3778
 
        ulint   offset, /*!< in: offset of the page within space in units of
 
2746
                        /* out: pointer to the block, page bufferfixed */
 
2747
        ulint   space,  /* in: space id */
 
2748
        ulint   offset, /* in: offset of the page within space in units of
3779
2749
                        a page */
3780
 
        ulint   zip_size,/*!< in: compressed page size, or 0 */
3781
 
        mtr_t*  mtr)    /*!< in: mini-transaction handle */
 
2750
        ulint   zip_size,/* in: compressed page size, or 0 */
 
2751
        mtr_t*  mtr)    /* in: mini-transaction handle */
3782
2752
{
3783
2753
        buf_frame_t*    frame;
3784
2754
        buf_block_t*    block;
3785
 
        ulint           fold;
3786
2755
        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
2756
 
3790
2757
        ut_ad(mtr);
3791
 
        ut_ad(mtr->state == MTR_ACTIVE);
3792
2758
        ut_ad(space || !zip_size);
3793
2759
 
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)) {
 
2760
        free_block = buf_LRU_get_free_block(0);
 
2761
 
 
2762
        buf_pool_mutex_enter();
 
2763
 
 
2764
        block = (buf_block_t*) buf_page_hash_get(space, offset);
 
2765
 
 
2766
        if (block && buf_page_in_file(&block->page)) {
3806
2767
#ifdef UNIV_IBUF_COUNT_DEBUG
3807
2768
                ut_a(ibuf_count_get(space, offset) == 0);
3808
2769
#endif
3811
2772
#endif /* UNIV_DEBUG_FILE_ACCESSES */
3812
2773
 
3813
2774
                /* Page can be found in buf_pool */
3814
 
                buf_pool_mutex_exit(buf_pool);
 
2775
                buf_pool_mutex_exit();
3815
2776
 
3816
2777
                buf_block_free(free_block);
3817
2778
 
3832
2793
 
3833
2794
        mutex_enter(&block->mutex);
3834
2795
 
3835
 
        buf_page_init(space, offset, fold, block);
 
2796
        buf_page_init(space, offset, block);
3836
2797
 
3837
2798
        /* The block must be put to the LRU list */
3838
2799
        buf_LRU_add_block(&block->page, FALSE);
3839
2800
 
3840
2801
        buf_block_buf_fix_inc(block, __FILE__, __LINE__);
3841
 
        buf_pool->stat.n_pages_created++;
 
2802
        buf_pool->n_pages_created++;
3842
2803
 
3843
2804
        if (zip_size) {
3844
2805
                void*   data;
3845
2806
                ibool   lru;
3846
2807
 
3847
2808
                /* Prevent race conditions during buf_buddy_alloc(),
3848
 
                which may release and reacquire buf_pool->mutex,
 
2809
                which may release and reacquire buf_pool_mutex,
3849
2810
                by IO-fixing and X-latching the block. */
3850
2811
 
3851
2812
                buf_page_set_io_fix(&block->page, BUF_IO_READ);
3853
2814
 
3854
2815
                page_zip_set_size(&block->page.zip, zip_size);
3855
2816
                mutex_exit(&block->mutex);
3856
 
                /* buf_pool->mutex may be released and reacquired by
 
2817
                /* buf_pool_mutex may be released and reacquired by
3857
2818
                buf_buddy_alloc().  Thus, we must release block->mutex
3858
2819
                in order not to break the latching order in
3859
 
                the reacquisition of buf_pool->mutex.  We also must
 
2820
                the reacquisition of buf_pool_mutex.  We also must
3860
2821
                defer this operation until after the block descriptor
3861
2822
                has been added to buf_pool->LRU and buf_pool->page_hash. */
3862
 
                data = buf_buddy_alloc(buf_pool, zip_size, &lru);
 
2823
                data = buf_buddy_alloc(zip_size, &lru);
3863
2824
                mutex_enter(&block->mutex);
3864
 
                block->page.zip.data = static_cast<unsigned char *>(data);
 
2825
                block->page.zip.data = data;
3865
2826
 
3866
2827
                /* To maintain the invariant
3867
2828
                block->in_unzip_LRU_list
3875
2836
                rw_lock_x_unlock(&block->lock);
3876
2837
        }
3877
2838
 
3878
 
        buf_page_set_accessed(&block->page, time_ms);
3879
 
 
3880
 
        buf_pool_mutex_exit(buf_pool);
 
2839
        buf_pool_mutex_exit();
3881
2840
 
3882
2841
        mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
3883
2842
 
 
2843
        buf_page_set_accessed(&block->page, TRUE);
 
2844
 
3884
2845
        mutex_exit(&block->mutex);
3885
2846
 
3886
2847
        /* Delete possible entries for the page from the insert buffer:
3889
2850
        ibuf_merge_or_delete_for_page(NULL, space, offset, zip_size, TRUE);
3890
2851
 
3891
2852
        /* Flush pages from the end of the LRU list if necessary */
3892
 
        buf_flush_free_margin(buf_pool);
 
2853
        buf_flush_free_margin();
3893
2854
 
3894
2855
        frame = block->frame;
3895
2856
 
3915
2876
        return(block);
3916
2877
}
3917
2878
 
3918
 
/********************************************************************//**
 
2879
/************************************************************************
3919
2880
Completes an asynchronous read or write request of a file page to or from
3920
2881
the buffer pool. */
3921
2882
UNIV_INTERN
3922
2883
void
3923
2884
buf_page_io_complete(
3924
2885
/*=================*/
3925
 
        buf_page_t*     bpage)  /*!< in: pointer to the block in question */
 
2886
        buf_page_t*     bpage)  /* in: pointer to the block in question */
3926
2887
{
3927
2888
        enum buf_io_fix io_type;
3928
 
        buf_pool_t*     buf_pool = buf_pool_from_bpage(bpage);
3929
2889
        const ibool     uncompressed = (buf_page_get_state(bpage)
3930
2890
                                        == BUF_BLOCK_FILE_PAGE);
3931
2891
 
4035
2995
                              " You can use CHECK\n"
4036
2996
                              "InnoDB: TABLE to scan your"
4037
2997
                              " table for corruption.\n"
4038
 
                              "InnoDB: See also "
4039
 
                              REFMAN "forcing-recovery.html\n"
 
2998
                              "InnoDB: See also"
 
2999
                              " http://dev.mysql.com/doc/refman/5.1/en/"
 
3000
                              "forcing-recovery.html\n"
4040
3001
                              "InnoDB: about forcing recovery.\n", stderr);
4041
3002
 
4042
3003
                        if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
4050
3011
                if (recv_recovery_is_on()) {
4051
3012
                        /* Pages must be uncompressed for crash recovery. */
4052
3013
                        ut_a(uncompressed);
4053
 
                        recv_recover_page(TRUE, (buf_block_t*) bpage);
 
3014
                        recv_recover_page(FALSE, TRUE, (buf_block_t*) bpage);
4054
3015
                }
4055
3016
 
4056
3017
                if (uncompressed && !recv_no_ibuf_operations) {
4061
3022
                }
4062
3023
        }
4063
3024
 
4064
 
        buf_pool_mutex_enter(buf_pool);
 
3025
        buf_pool_mutex_enter();
4065
3026
        mutex_enter(buf_page_get_mutex(bpage));
4066
3027
 
4067
3028
#ifdef UNIV_IBUF_COUNT_DEBUG
4087
3048
 
4088
3049
                ut_ad(buf_pool->n_pend_reads > 0);
4089
3050
                buf_pool->n_pend_reads--;
4090
 
                buf_pool->stat.n_pages_read++;
 
3051
                buf_pool->n_pages_read++;
4091
3052
 
4092
3053
                if (uncompressed) {
4093
3054
                        rw_lock_x_unlock_gen(&((buf_block_t*) bpage)->lock,
4107
3068
                                             BUF_IO_WRITE);
4108
3069
                }
4109
3070
 
4110
 
                buf_pool->stat.n_pages_written++;
 
3071
                buf_pool->n_pages_written++;
4111
3072
 
4112
3073
                break;
4113
3074
 
4125
3086
#endif /* UNIV_DEBUG */
4126
3087
 
4127
3088
        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
 
3089
        buf_pool_mutex_exit();
 
3090
}
 
3091
 
 
3092
/*************************************************************************
 
3093
Invalidates the file pages in the buffer pool when an archive recovery is
 
3094
completed. All the file pages buffered must be in a replaceable state when
 
3095
this function is called: not latched and not modified. */
 
3096
UNIV_INTERN
4170
3097
void
4171
 
buf_pool_invalidate_instance(
4172
 
/*=========================*/
4173
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3098
buf_pool_invalidate(void)
 
3099
/*=====================*/
4174
3100
{
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));
 
3101
        ibool   freed;
 
3102
 
 
3103
        ut_ad(buf_all_freed());
4203
3104
 
4204
3105
        freed = TRUE;
4205
3106
 
4206
3107
        while (freed) {
4207
 
                freed = buf_LRU_search_and_free_block(buf_pool, 100);
 
3108
                freed = buf_LRU_search_and_free_block(100);
4208
3109
        }
4209
3110
 
4210
 
        buf_pool_mutex_enter(buf_pool);
 
3111
        buf_pool_mutex_enter();
4211
3112
 
4212
3113
        ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
4213
3114
        ut_ad(UT_LIST_GET_LEN(buf_pool->unzip_LRU) == 0);
4214
3115
 
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);
 
3116
        buf_pool_mutex_exit();
4224
3117
}
4225
3118
 
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. */
 
3119
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
 
3120
/*************************************************************************
 
3121
Validates the buffer buf_pool data structure. */
4230
3122
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
 
        }
4240
 
}
4241
 
 
4242
 
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4243
 
/*********************************************************************//**
4244
 
Validates data in one buffer pool instance
4245
 
@return TRUE */
4246
 
static
4247
3123
ibool
4248
 
buf_pool_validate_instance(
4249
 
/*=======================*/
4250
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3124
buf_validate(void)
 
3125
/*==============*/
4251
3126
{
4252
3127
        buf_page_t*     b;
4253
3128
        buf_chunk_t*    chunk;
4262
3137
 
4263
3138
        ut_ad(buf_pool);
4264
3139
 
4265
 
        buf_pool_mutex_enter(buf_pool);
 
3140
        buf_pool_mutex_enter();
4266
3141
 
4267
3142
        chunk = buf_pool->chunks;
4268
3143
 
4287
3162
                                break;
4288
3163
 
4289
3164
                        case BUF_BLOCK_FILE_PAGE:
4290
 
                                ut_a(buf_page_hash_get(buf_pool,
4291
 
                                                       buf_block_get_space(
 
3165
                                ut_a(buf_page_hash_get(buf_block_get_space(
4292
3166
                                                               block),
4293
3167
                                                       buf_block_get_page_no(
4294
3168
                                                               block))
4335
3209
                                }
4336
3210
 
4337
3211
                                n_lru++;
 
3212
 
 
3213
                                if (block->page.oldest_modification > 0) {
 
3214
                                        n_flush++;
 
3215
                                }
 
3216
 
4338
3217
                                break;
4339
3218
 
4340
3219
                        case BUF_BLOCK_NOT_USED:
4352
3231
                }
4353
3232
        }
4354
3233
 
4355
 
        mutex_enter(&buf_pool->zip_mutex);
 
3234
        mutex_enter(&buf_pool_zip_mutex);
4356
3235
 
4357
3236
        /* Check clean compressed-only blocks. */
4358
3237
 
4373
3252
                        ut_error;
4374
3253
                        break;
4375
3254
                }
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
3255
                ut_a(!b->oldest_modification);
4381
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3256
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4382
3257
 
4383
3258
                n_lru++;
4384
3259
                n_zip++;
4385
3260
        }
4386
3261
 
4387
 
        /* Check dirty blocks. */
 
3262
        /* Check dirty compressed-only blocks. */
4388
3263
 
4389
 
        buf_flush_list_mutex_enter(buf_pool);
4390
3264
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4391
3265
             b = UT_LIST_GET_NEXT(list, b)) {
4392
3266
                ut_ad(b->in_flush_list);
4393
 
                ut_a(b->oldest_modification);
4394
 
                n_flush++;
4395
3267
 
4396
3268
                switch (buf_page_get_state(b)) {
4397
3269
                case BUF_BLOCK_ZIP_DIRTY:
 
3270
                        ut_a(b->oldest_modification);
4398
3271
                        n_lru++;
 
3272
                        n_flush++;
4399
3273
                        n_zip++;
4400
3274
                        switch (buf_page_get_io_fix(b)) {
4401
3275
                        case BUF_IO_NONE:
4402
3276
                        case BUF_IO_READ:
4403
3277
                                break;
 
3278
 
4404
3279
                        case BUF_IO_WRITE:
4405
3280
                                switch (buf_page_get_flush_type(b)) {
4406
3281
                                case BUF_FLUSH_LRU:
4430
3305
                        ut_error;
4431
3306
                        break;
4432
3307
                }
4433
 
                ut_a(buf_page_hash_get(buf_pool, b->space, b->offset) == b);
 
3308
                ut_a(buf_page_hash_get(b->space, b->offset) == b);
4434
3309
        }
4435
3310
 
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);
 
3311
        mutex_exit(&buf_pool_zip_mutex);
4441
3312
 
4442
3313
        if (n_lru + n_free > buf_pool->curr_size + n_zip) {
4443
3314
                fprintf(stderr, "n LRU %lu, n free %lu, pool %lu zip %lu\n",
4453
3324
                        (ulong) n_free);
4454
3325
                ut_error;
4455
3326
        }
 
3327
        ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
4456
3328
 
4457
3329
        ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
4458
3330
        ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
4459
3331
        ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
4460
3332
 
4461
 
        buf_pool_mutex_exit(buf_pool);
 
3333
        buf_pool_mutex_exit();
4462
3334
 
4463
3335
        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
 
 
 
3336
        ut_a(buf_flush_validate());
 
3337
 
 
3338
        return(TRUE);
 
3339
}
4489
3340
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
4490
3341
 
4491
3342
#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
4492
 
/*********************************************************************//**
4493
 
Prints info of the buffer buf_pool data structure for one instance. */
4494
 
static
 
3343
/*************************************************************************
 
3344
Prints info of the buffer buf_pool data structure. */
 
3345
UNIV_INTERN
4495
3346
void
4496
 
buf_print_instance(
4497
 
/*===============*/
4498
 
        buf_pool_t*     buf_pool)
 
3347
buf_print(void)
 
3348
/*===========*/
4499
3349
{
4500
 
        index_id_t*     index_ids;
 
3350
        dulint*         index_ids;
4501
3351
        ulint*          counts;
4502
3352
        ulint           size;
4503
3353
        ulint           i;
4504
3354
        ulint           j;
4505
 
        index_id_t      id;
 
3355
        dulint          id;
4506
3356
        ulint           n_found;
4507
3357
        buf_chunk_t*    chunk;
4508
3358
        dict_index_t*   index;
4511
3361
 
4512
3362
        size = buf_pool->curr_size;
4513
3363
 
4514
 
        index_ids = mem_alloc(size * sizeof *index_ids);
 
3364
        index_ids = mem_alloc(sizeof(dulint) * size);
4515
3365
        counts = mem_alloc(sizeof(ulint) * size);
4516
3366
 
4517
 
        buf_pool_mutex_enter(buf_pool);
4518
 
        buf_flush_list_mutex_enter(buf_pool);
 
3367
        buf_pool_mutex_enter();
4519
3368
 
4520
3369
        fprintf(stderr,
4521
3370
                "buf_pool size %lu\n"
4525
3374
                "n pending decompressions %lu\n"
4526
3375
                "n pending reads %lu\n"
4527
3376
                "n pending flush LRU %lu list %lu single page %lu\n"
4528
 
                "pages made young %lu, not young %lu\n"
4529
3377
                "pages read %lu, created %lu, written %lu\n",
4530
3378
                (ulong) size,
4531
3379
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4536
3384
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU],
4537
3385
                (ulong) buf_pool->n_flush[BUF_FLUSH_LIST],
4538
3386
                (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);
 
3387
                (ulong) buf_pool->n_pages_read, buf_pool->n_pages_created,
 
3388
                (ulong) buf_pool->n_pages_written);
4546
3389
 
4547
3390
        /* Count the number of blocks belonging to each index in the buffer */
4548
3391
 
4566
3409
 
4567
3410
                                while (j < n_found) {
4568
3411
 
4569
 
                                        if (index_ids[j] == id) {
 
3412
                                        if (ut_dulint_cmp(index_ids[j],
 
3413
                                                          id) == 0) {
4570
3414
                                                counts[j]++;
4571
3415
 
4572
3416
                                                break;
4583
3427
                }
4584
3428
        }
4585
3429
 
4586
 
        buf_pool_mutex_exit(buf_pool);
 
3430
        buf_pool_mutex_exit();
4587
3431
 
4588
3432
        for (i = 0; i < n_found; i++) {
4589
3433
                index = dict_index_get_if_in_cache(index_ids[i]);
4590
3434
 
4591
3435
                fprintf(stderr,
4592
 
                        "Block count for index %llu in buffer is about %lu",
4593
 
                        (ullint) index_ids[i],
 
3436
                        "Block count for index %lu in buffer is about %lu",
 
3437
                        (ulong) ut_dulint_get_low(index_ids[i]),
4594
3438
                        (ulong) counts[i]);
4595
3439
 
4596
3440
                if (index) {
4604
3448
        mem_free(index_ids);
4605
3449
        mem_free(counts);
4606
3450
 
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
 
        }
 
3451
        ut_a(buf_validate());
4625
3452
}
4626
3453
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
4627
3454
 
4628
3455
#ifdef UNIV_DEBUG
4629
 
/*********************************************************************//**
4630
 
Returns the number of latched pages in the buffer pool.
4631
 
@return number of latched pages */
 
3456
/*************************************************************************
 
3457
Returns the number of latched pages in the buffer pool. */
4632
3458
UNIV_INTERN
4633
3459
ulint
4634
 
buf_get_latched_pages_number_instance(
4635
 
/*==================================*/
4636
 
        buf_pool_t*     buf_pool)       /*!< in: buffer pool instance */
 
3460
buf_get_latched_pages_number(void)
 
3461
/*==============================*/
4637
3462
{
 
3463
        buf_chunk_t*    chunk;
4638
3464
        buf_page_t*     b;
4639
3465
        ulint           i;
4640
 
        buf_chunk_t*    chunk;
4641
3466
        ulint           fixed_pages_number = 0;
4642
3467
 
4643
 
        buf_pool_mutex_enter(buf_pool);
 
3468
        buf_pool_mutex_enter();
4644
3469
 
4645
3470
        chunk = buf_pool->chunks;
4646
3471
 
4669
3494
                }
4670
3495
        }
4671
3496
 
4672
 
        mutex_enter(&buf_pool->zip_mutex);
 
3497
        mutex_enter(&buf_pool_zip_mutex);
4673
3498
 
4674
3499
        /* Traverse the lists of clean and dirty compressed-only blocks. */
4675
3500
 
4684
3509
                }
4685
3510
        }
4686
3511
 
4687
 
        buf_flush_list_mutex_enter(buf_pool);
4688
3512
        for (b = UT_LIST_GET_FIRST(buf_pool->flush_list); b;
4689
3513
             b = UT_LIST_GET_NEXT(list, b)) {
4690
3514
                ut_ad(b->in_flush_list);
4710
3534
                }
4711
3535
        }
4712
3536
 
4713
 
        buf_flush_list_mutex_exit(buf_pool);
4714
 
        mutex_exit(&buf_pool->zip_mutex);
4715
 
        buf_pool_mutex_exit(buf_pool);
 
3537
        mutex_exit(&buf_pool_zip_mutex);
 
3538
        buf_pool_mutex_exit();
4716
3539
 
4717
3540
        return(fixed_pages_number);
4718
3541
}
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
3542
#endif /* UNIV_DEBUG */
4744
3543
 
4745
 
/*********************************************************************//**
4746
 
Returns the number of pending buf pool ios.
4747
 
@return number of pending I/O operations */
 
3544
/*************************************************************************
 
3545
Returns the number of pending buf pool ios. */
4748
3546
UNIV_INTERN
4749
3547
ulint
4750
3548
buf_get_n_pending_ios(void)
4751
3549
/*=======================*/
4752
3550
{
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);
 
3551
        return(buf_pool->n_pend_reads
 
3552
               + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3553
               + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3554
               + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4769
3555
}
4770
3556
 
4771
 
/*********************************************************************//**
 
3557
/*************************************************************************
4772
3558
Returns the ratio in percents of modified pages in the buffer pool /
4773
 
database pages in the buffer pool.
4774
 
@return modified page percentage ratio */
 
3559
database pages in the buffer pool. */
4775
3560
UNIV_INTERN
4776
3561
ulint
4777
3562
buf_get_modified_ratio_pct(void)
4778
3563
/*============================*/
4779
3564
{
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
 
  
 
3565
        ulint   ratio;
 
3566
 
 
3567
        buf_pool_mutex_enter();
 
3568
 
 
3569
        ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
 
3570
                / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
 
3571
                   + UT_LIST_GET_LEN(buf_pool->free));
 
3572
 
4789
3573
        /* 1 + is there to avoid division by zero */
4790
3574
 
 
3575
        buf_pool_mutex_exit();
 
3576
 
4791
3577
        return(ratio);
4792
3578
}
4793
3579
 
4794
 
/*********************************************************************//**
 
3580
/*************************************************************************
4795
3581
Prints info of the buffer i/o. */
4796
 
static
 
3582
UNIV_INTERN
4797
3583
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 */
 
3584
buf_print_io(
 
3585
/*=========*/
 
3586
        FILE*   file)   /* in/out: buffer where to print */
4802
3587
{
4803
3588
        time_t  current_time;
4804
3589
        double  time_elapsed;
4805
 
        ulint   n_gets_diff;
 
3590
        ulint   size;
4806
3591
 
4807
3592
        ut_ad(buf_pool);
 
3593
        size = buf_pool->curr_size;
4808
3594
 
4809
 
        buf_pool_mutex_enter(buf_pool);
4810
 
        buf_flush_list_mutex_enter(buf_pool);
 
3595
        buf_pool_mutex_enter();
4811
3596
 
4812
3597
        fprintf(file,
4813
3598
                "Buffer pool size   %lu\n"
4814
3599
                "Free buffers       %lu\n"
4815
3600
                "Database pages     %lu\n"
4816
 
                "Old database pages %lu\n"
4817
3601
                "Modified db pages  %lu\n"
4818
3602
                "Pending reads %lu\n"
4819
3603
                "Pending writes: LRU %lu, flush list %lu, single page %lu\n",
4820
 
                (ulong) buf_pool->curr_size,
 
3604
                (ulong) size,
4821
3605
                (ulong) UT_LIST_GET_LEN(buf_pool->free),
4822
3606
                (ulong) UT_LIST_GET_LEN(buf_pool->LRU),
4823
 
                (ulong) buf_pool->LRU_old_len,
4824
3607
                (ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
4825
3608
                (ulong) buf_pool->n_pend_reads,
4826
3609
                (ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
4829
3612
                + buf_pool->init_flush[BUF_FLUSH_LIST],
4830
3613
                (ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
4831
3614
 
4832
 
        buf_flush_list_mutex_exit(buf_pool);
4833
 
 
4834
3615
        current_time = time(NULL);
4835
3616
        time_elapsed = 0.001 + difftime(current_time,
4836
3617
                                        buf_pool->last_printout_time);
 
3618
        buf_pool->last_printout_time = current_time;
4837
3619
 
4838
3620
        fprintf(file,
4839
 
                "Pages made young %lu, not young %lu\n"
4840
 
                "%.2f youngs/s, %.2f non-youngs/s\n"
4841
3621
                "Pages read %lu, created %lu, written %lu\n"
4842
3622
                "%.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)
 
3623
                (ulong) buf_pool->n_pages_read,
 
3624
                (ulong) buf_pool->n_pages_created,
 
3625
                (ulong) buf_pool->n_pages_written,
 
3626
                (buf_pool->n_pages_read - buf_pool->n_pages_read_old)
 
3627
                / time_elapsed,
 
3628
                (buf_pool->n_pages_created - buf_pool->n_pages_created_old)
 
3629
                / time_elapsed,
 
3630
                (buf_pool->n_pages_written - buf_pool->n_pages_written_old)
4862
3631
                / time_elapsed);
4863
3632
 
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));
 
3633
        if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
 
3634
                fprintf(file, "Buffer pool hit rate %lu / 1000\n",
 
3635
                        (ulong)
 
3636
                        (1000 - ((1000 * (buf_pool->n_pages_read
 
3637
                                          - buf_pool->n_pages_read_old))
 
3638
                                 / (buf_pool->n_page_gets
 
3639
                                    - buf_pool->n_page_gets_old))));
4884
3640
        } else {
4885
3641
                fputs("No buffer pool page gets since the last printout\n",
4886
3642
                      file);
4887
3643
        }
4888
3644
 
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);
 
3645
        buf_pool->n_page_gets_old = buf_pool->n_page_gets;
 
3646
        buf_pool->n_pages_read_old = buf_pool->n_pages_read;
 
3647
        buf_pool->n_pages_created_old = buf_pool->n_pages_created;
 
3648
        buf_pool->n_pages_written_old = buf_pool->n_pages_written;
4898
3649
 
4899
3650
        /* Print some values to help us with visualizing what is
4900
3651
        happening with LRU eviction. */
4901
3652
        fprintf(file,
4902
3653
                "LRU len: %lu, unzip_LRU len: %lu\n"
4903
3654
                "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)),
 
3655
                UT_LIST_GET_LEN(buf_pool->LRU),
 
3656
                UT_LIST_GET_LEN(buf_pool->unzip_LRU),
4906
3657
                buf_LRU_stat_sum.io, buf_LRU_stat_cur.io,
4907
3658
                buf_LRU_stat_sum.unzip, buf_LRU_stat_cur.unzip);
4908
3659
 
4909
 
        buf_refresh_io_stats(buf_pool);
4910
 
        buf_pool_mutex_exit(buf_pool);
4911
 
}
4912
 
 
4913
 
/*********************************************************************//**
4914
 
Prints info of the buffer i/o. */
4915
 
UNIV_INTERN
4916
 
void
4917
 
buf_print_io(
4918
 
/*=========*/
4919
 
        FILE*   file)   /*!< in/out: buffer where to print */
4920
 
{
4921
 
        ulint   i;
4922
 
 
4923
 
        for (i = 0; i < srv_buf_pool_instances; i++) {
4924
 
                buf_pool_t*     buf_pool;
4925
 
 
4926
 
                buf_pool = buf_pool_from_array(i);
4927
 
                buf_print_io_instance(buf_pool, file);
4928
 
        }
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 */
 
3660
        buf_pool_mutex_exit();
 
3661
}
 
3662
 
 
3663
/**************************************************************************
 
3664
Refreshes the statistics used to print per-second averages. */
 
3665
UNIV_INTERN
 
3666
void
 
3667
buf_refresh_io_stats(void)
 
3668
/*======================*/
 
3669
{
 
3670
        buf_pool->last_printout_time = time(NULL);
 
3671
        buf_pool->n_page_gets_old = buf_pool->n_page_gets;
 
3672
        buf_pool->n_pages_read_old = buf_pool->n_pages_read;
 
3673
        buf_pool->n_pages_created_old = buf_pool->n_pages_created;
 
3674
        buf_pool->n_pages_written_old = buf_pool->n_pages_written;
 
3675
}
 
3676
 
 
3677
/*************************************************************************
 
3678
Checks that all file pages in the buffer are in a replaceable state. */
4964
3679
UNIV_INTERN
4965
3680
ibool
4966
3681
buf_all_freed(void)
4967
3682
/*===============*/
4968
3683
{
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);
 
3684
        buf_chunk_t*    chunk;
 
3685
        ulint           i;
 
3686
 
 
3687
        ut_ad(buf_pool);
 
3688
 
 
3689
        buf_pool_mutex_enter();
 
3690
 
 
3691
        chunk = buf_pool->chunks;
 
3692
 
 
3693
        for (i = buf_pool->n_chunks; i--; chunk++) {
 
3694
 
 
3695
                const buf_block_t* block = buf_chunk_not_freed(chunk);
 
3696
 
 
3697
                if (UNIV_LIKELY_NULL(block)) {
 
3698
                        fprintf(stderr,
 
3699
                                "Page %lu %lu still fixed or dirty\n",
 
3700
                                (ulong) block->page.space,
 
3701
                                (ulong) block->page.offset);
 
3702
                        ut_error;
4978
3703
                }
4979
 
        }
 
3704
        }
 
3705
 
 
3706
        buf_pool_mutex_exit();
4980
3707
 
4981
3708
        return(TRUE);
4982
3709
}
4983
 
  
4984
 
/*********************************************************************//**
 
3710
 
 
3711
/*************************************************************************
4985
3712
Checks that there currently are no pending i/o-operations for the buffer
4986
 
pool.
4987
 
@return TRUE if there is no pending i/o */
 
3713
pool. */
4988
3714
UNIV_INTERN
4989
3715
ibool
4990
3716
buf_pool_check_no_pending_io(void)
4991
3717
/*==============================*/
 
3718
                                /* out: TRUE if there is no pending i/o */
4992
3719
{
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
 
                }
 
3720
        ibool   ret;
 
3721
 
 
3722
        buf_pool_mutex_enter();
 
3723
 
 
3724
        if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
 
3725
            + buf_pool->n_flush[BUF_FLUSH_LIST]
 
3726
            + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
 
3727
                ret = FALSE;
 
3728
        } else {
 
3729
                ret = TRUE;
5010
3730
        }
5011
3731
 
5012
 
        buf_pool_mutex_exit_all();
 
3732
        buf_pool_mutex_exit();
5013
3733
 
5014
3734
        return(ret);
5015
3735
}
5016
3736
 
5017
 
#if 0
5018
 
Code currently not used
5019
 
/*********************************************************************//**
5020
 
Gets the current length of the free list of buffer blocks.
5021
 
@return length of the free list */
 
3737
/*************************************************************************
 
3738
Gets the current length of the free list of buffer blocks. */
5022
3739
UNIV_INTERN
5023
3740
ulint
5024
3741
buf_get_free_list_len(void)
5026
3743
{
5027
3744
        ulint   len;
5028
3745
 
5029
 
        buf_pool_mutex_enter(buf_pool);
 
3746
        buf_pool_mutex_enter();
5030
3747
 
5031
3748
        len = UT_LIST_GET_LEN(buf_pool->free);
5032
3749
 
5033
 
        buf_pool_mutex_exit(buf_pool);
 
3750
        buf_pool_mutex_exit();
5034
3751
 
5035
3752
        return(len);
5036
3753
}
5037
 
#endif
5038
 
 
5039
 
#else /* !UNIV_HOTBACKUP */
5040
 
/********************************************************************//**
5041
 
Inits a page to the buffer buf_pool, for use in ibbackup --restore. */
5042
 
UNIV_INTERN
5043
 
void
5044
 
buf_page_init_for_backup_restore(
5045
 
/*=============================*/
5046
 
        ulint           space,  /*!< in: space id */
5047
 
        ulint           offset, /*!< in: offset of the page within space
5048
 
                                in units of a page */
5049
 
        ulint           zip_size,/*!< in: compressed page size in bytes
5050
 
                                or 0 for uncompressed pages */
5051
 
        buf_block_t*    block)  /*!< in: block to init */
5052
 
{
5053
 
        block->page.state       = BUF_BLOCK_FILE_PAGE;
5054
 
        block->page.space       = space;
5055
 
        block->page.offset      = offset;
5056
 
 
5057
 
        page_zip_des_init(&block->page.zip);
5058
 
 
5059
 
        /* We assume that block->page.data has been allocated
5060
 
        with zip_size == UNIV_PAGE_SIZE. */
5061
 
        ut_ad(zip_size <= UNIV_PAGE_SIZE);
5062
 
        ut_ad(ut_is_2pow(zip_size));
5063
 
        page_zip_set_size(&block->page.zip, zip_size);
5064
 
        if (zip_size) {
5065
 
                block->page.zip.data = block->frame + UNIV_PAGE_SIZE;
5066
 
        }
5067
 
}
5068
 
#endif /* !UNIV_HOTBACKUP */