summaryrefslogtreecommitdiff
path: root/storage/innobase/buf/buf0rea.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/buf/buf0rea.cc')
-rw-r--r--storage/innobase/buf/buf0rea.cc579
1 files changed, 280 insertions, 299 deletions
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc
index 285fc465160..5de0412afb2 100644
--- a/storage/innobase/buf/buf0rea.cc
+++ b/storage/innobase/buf/buf0rea.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015. MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -24,11 +24,12 @@ The database buffer read
Created 11/5/1995 Heikki Tuuri
*******************************************************/
-#include "buf0rea.h"
+#include "ha_prototypes.h"
+#include <mysql/service_thd_wait.h>
+#include "buf0rea.h"
#include "fil0fil.h"
#include "mtr0mtr.h"
-
#include "buf0buf.h"
#include "buf0flu.h"
#include "buf0lru.h"
@@ -39,8 +40,6 @@ Created 11/5/1995 Heikki Tuuri
#include "os0file.h"
#include "srv0start.h"
#include "srv0srv.h"
-#include "mysql/plugin.h"
-#include "mysql/service_thd_wait.h"
/** There must be at least this many pages in buf_pool in the area to start
a random read-ahead */
@@ -91,62 +90,50 @@ buf_read_page_handle_error(
buf_pool_mutex_exit(buf_pool);
}
-/********************************************************************//**
-Low-level function which reads a page asynchronously from a file to the
+/** Low-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there, in which case does nothing.
Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
flag is cleared and the x-lock released by an i/o-handler thread.
+
+@param[out] err DB_SUCCESS, DB_TABLESPACE_DELETED or
+ DB_TABLESPACE_TRUNCATED if we are trying
+ to read from a non-existent tablespace, a
+ tablespace which is just now being dropped,
+ or a tablespace which is truncated
+@param[in] sync true if synchronous aio is desired
+@param[in] type IO type, SIMULATED, IGNORE_MISSING
+@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...,
+@param[in] page_id page id
+@param[in] unzip true=request uncompressed page
@return 1 if a read request was queued, 0 if the page already resided
in buf_pool, or if the page is in the doublewrite buffer blocks in
which case it is never read into the pool, or if the tablespace does
-not exist or is being dropped
-@return 1 if read request is issued. 0 if it is not */
+not exist or is being dropped */
static
ulint
buf_read_page_low(
-/*==============*/
- dberr_t* err, /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
- trying to read from a non-existent tablespace, or a
- tablespace which is just now being dropped */
- bool sync, /*!< in: true if synchronous aio is desired */
- ulint mode, /*!< in: BUF_READ_IBUF_PAGES_ONLY, ...,
- ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
- at read-ahead functions) */
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size, or 0 */
- ibool unzip, /*!< in: TRUE=request uncompressed page */
- ib_int64_t tablespace_version, /*!< in: if the space memory object has
- this timestamp different from what we are giving here,
- treat the tablespace as dropped; this is a timestamp we
- use to stop dangling page reads from a tablespace
- which we have DISCARDed + IMPORTed back */
- ulint offset, /*!< in: page number */
+ dberr_t* err,
+ bool sync,
+ ulint type,
+ ulint mode,
+ const page_id_t& page_id,
+ const page_size_t& page_size,
+ bool unzip,
buf_page_t** rbpage) /*!< out: page */
{
buf_page_t* bpage;
- ulint wake_later;
- ibool ignore_nonexistent_pages;
*err = DB_SUCCESS;
- wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
- mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
-
- ignore_nonexistent_pages = mode & BUF_READ_IGNORE_NONEXISTENT_PAGES;
- mode &= ~BUF_READ_IGNORE_NONEXISTENT_PAGES;
-
- if (space == TRX_SYS_SPACE && buf_dblwr_page_inside(offset)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Warning: trying to read"
- " doublewrite buffer page %lu\n",
- (ulong) offset);
+ if (page_id.space() == TRX_SYS_SPACE
+ && buf_dblwr_page_inside(page_id.page_no())) {
+ ib::error() << "Trying to read doublewrite buffer page "
+ << page_id;
return(0);
}
- if (ibuf_bitmap_page(zip_size, offset)
- || trx_sys_hdr_page(space, offset)) {
+ if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
/* Trx sys header is so low in the latching order that we play
safe and do not leave the i/o-completion to an asynchronous
@@ -161,60 +148,81 @@ buf_read_page_low(
or is being dropped; if we succeed in initing the page in the buffer
pool for read, then DISCARD cannot proceed until the read has
completed */
- bpage = buf_page_init_for_read(err, mode, space, zip_size, unzip,
- tablespace_version, offset);
+ bpage = buf_page_init_for_read(err, mode, page_id, page_size, unzip);
+
if (bpage == NULL) {
return(0);
}
-#ifdef UNIV_DEBUG
- if (buf_debug_prints) {
- fprintf(stderr,
- "Posting read request for page %lu, sync %s\n",
- (ulong) offset, sync ? "true" : "false");
- }
-#endif
+ DBUG_PRINT("ib_buf", ("read page %u:%u size=%u unzip=%u,%s",
+ (unsigned) page_id.space(),
+ (unsigned) page_id.page_no(),
+ (unsigned) page_size.physical(),
+ (unsigned) unzip,
+ sync ? "sync" : "async"));
ut_ad(buf_page_in_file(bpage));
- byte* frame = zip_size ? bpage->zip.data : ((buf_block_t*) bpage)->frame;
-
if (sync) {
thd_wait_begin(NULL, THD_WAIT_DISKIO);
}
- if (zip_size) {
- *err = fil_io(OS_FILE_READ | wake_later
- | ignore_nonexistent_pages,
- sync, space, zip_size, offset, 0, zip_size,
- frame, bpage, &bpage->write_size);
+ void* dst;
+
+ if (page_size.is_compressed()) {
+ dst = bpage->zip.data;
} else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
- *err = fil_io(OS_FILE_READ | wake_later
- | ignore_nonexistent_pages,
- sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
- frame, bpage,
- &bpage->write_size);
+ dst = ((buf_block_t*) bpage)->frame;
}
+ IORequest request(type | IORequest::READ);
+
+ ut_ad(dst != NULL);
+ ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL);
+
+ *err = fil_io(
+ request, sync, page_id, page_size, 0, page_size.physical(),
+ dst, bpage, NULL);
+
+ ut_ad(dst != NULL);
+ ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL);
+ ut_ad(bpage->id.space() == page_id.space());
+
if (sync) {
thd_wait_end(NULL);
}
if (*err != DB_SUCCESS) {
- if (ignore_nonexistent_pages || *err == DB_TABLESPACE_DELETED) {
+ if (*err == DB_TABLESPACE_TRUNCATED) {
+ /* Remove the page which is outside the
+ truncated tablespace bounds when recovering
+ from a crash happened during a truncation */
+ buf_read_page_handle_error(bpage);
+ if (recv_recovery_on) {
+ mutex_enter(&recv_sys->mutex);
+ ut_ad(recv_sys->n_addrs > 0);
+ recv_sys->n_addrs--;
+ mutex_exit(&recv_sys->mutex);
+ }
+ return(0);
+ } else if (IORequest::ignore_missing(type)
+ || *err == DB_TABLESPACE_DELETED) {
buf_read_page_handle_error(bpage);
return(0);
}
- /* else */
+
ut_error;
}
if (sync) {
+ ut_ad(dst != NULL);
+ ut_ad(bpage->zip.data != NULL || ((buf_block_t*)bpage)->frame != NULL);
/* The i/o is already completed when we arrive from
fil_read */
+
if (!buf_page_io_complete(bpage)) {
if (rbpage) {
*rbpage = bpage;
@@ -230,8 +238,7 @@ buf_read_page_low(
return(1);
}
-/********************************************************************//**
-Applies a random read-ahead in buf_pool if there are at least a threshold
+/** Applies a random read-ahead in buf_pool if there are at least a threshold
value of accessed pages from the random read-ahead area. Does not read any
page, not even the one at the position (space, offset), if the read-ahead
mechanism is not activated. NOTE 1: the calling thread may own latches on
@@ -240,24 +247,20 @@ end up waiting for these latches! NOTE 2: the calling thread must want
access to the page given: this rule is set to prevent unintended read-aheads
performed by ibuf routines, a situation which could result in a deadlock if
the OS does not support asynchronous i/o.
+@param[in] page_id page id of a page which the current thread
+wants to access
+@param[in] page_size page size
+@param[in] inside_ibuf TRUE if we are inside ibuf routine
@return number of page read requests issued; NOTE that if we read ibuf
pages, it may happen that the page at the given page number does not
-get read even if we return a positive value!
-@return number of page read requests issued */
-UNIV_INTERN
+get read even if we return a positive value! */
ulint
buf_read_ahead_random(
-/*==================*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes,
- or 0 */
- ulint offset, /*!< in: page number of a page which
- the current thread wants to access */
- ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf
- routine */
+ const page_id_t& page_id,
+ const page_size_t& page_size,
+ ibool inside_ibuf)
{
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
- ib_int64_t tablespace_version;
+ buf_pool_t* buf_pool = buf_pool_get(page_id);
ulint recent_blocks = 0;
ulint ibuf_mode;
ulint count;
@@ -277,8 +280,7 @@ buf_read_ahead_random(
return(0);
}
- if (ibuf_bitmap_page(zip_size, offset)
- || trx_sys_hdr_page(space, offset)) {
+ if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
@@ -287,19 +289,22 @@ buf_read_ahead_random(
return(0);
}
- /* Remember the tablespace version before we ask te tablespace size
- below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
- do not try to read outside the bounds of the tablespace! */
-
- tablespace_version = fil_space_get_version(space);
-
- low = (offset / buf_read_ahead_random_area)
+ low = (page_id.page_no() / buf_read_ahead_random_area)
* buf_read_ahead_random_area;
- high = (offset / buf_read_ahead_random_area + 1)
+
+ high = (page_id.page_no() / buf_read_ahead_random_area + 1)
* buf_read_ahead_random_area;
- if (high > fil_space_get_size(space)) {
- high = fil_space_get_size(space);
+ /* Remember the tablespace version before we ask the tablespace size
+ below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
+ do not try to read outside the bounds of the tablespace! */
+ if (fil_space_t* space = fil_space_acquire(page_id.space())) {
+ if (high > space->size) {
+ high = space->size;
+ }
+ fil_space_release(space);
+ } else {
+ return(0);
}
buf_pool_mutex_enter(buf_pool);
@@ -315,10 +320,10 @@ buf_read_ahead_random(
that is, reside near the start of the LRU list. */
for (i = low; i < high; i++) {
- const buf_page_t* bpage =
- buf_page_hash_get(buf_pool, space, i);
+ const buf_page_t* bpage = buf_page_hash_get(
+ buf_pool, page_id_t(page_id.space(), i));
- if (bpage
+ if (bpage != NULL
&& buf_page_is_accessed(bpage)
&& buf_page_peek_if_young(bpage)) {
@@ -352,21 +357,22 @@ read_ahead:
/* It is only sensible to do read-ahead in the non-sync aio
mode: hence FALSE as the first parameter */
- if (!ibuf_bitmap_page(zip_size, i)) {
+ const page_id_t cur_page_id(page_id.space(), i);
+
+ if (!ibuf_bitmap_page(cur_page_id, page_size)) {
+ buf_page_t* rpage = NULL;
count += buf_read_page_low(
&err, false,
- ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
- space, zip_size, FALSE,
- tablespace_version, i, NULL);
+ IORequest::DO_NOT_WAKE,
+ ibuf_mode,
+ cur_page_id, page_size, false, &rpage);
+
if (err == DB_TABLESPACE_DELETED) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Warning: in random"
- " readahead trying to access\n"
- "InnoDB: tablespace %lu page %lu,\n"
- "InnoDB: but the tablespace does not"
- " exist or is just being dropped.\n",
- (ulong) space, (ulong) i);
+ ib::warn() << "Random readahead trying to"
+ " access page " << cur_page_id
+ << " in nonexisting or"
+ " being-dropped tablespace";
+ break;
}
}
}
@@ -377,14 +383,12 @@ read_ahead:
os_aio_simulated_wake_handler_threads();
-#ifdef UNIV_DEBUG
- if (buf_debug_prints && (count > 0)) {
- fprintf(stderr,
- "Random read-ahead space %lu offset %lu pages %lu\n",
- (ulong) space, (ulong) offset,
- (ulong) count);
+ if (count) {
+ DBUG_PRINT("ib_buf", ("random read-ahead %u pages, %u:%u",
+ (unsigned) count,
+ (unsigned) page_id.space(),
+ (unsigned) page_id.page_no()));
}
-#endif /* UNIV_DEBUG */
/* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */
@@ -395,42 +399,37 @@ read_ahead:
return(count);
}
-/********************************************************************//**
-High-level function which reads a page asynchronously from a file to the
+/** High-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
+@param[in] page_id page id
+@param[in] page_size page size
@return TRUE if page has been read in, FALSE in case of failure */
-UNIV_INTERN
ibool
buf_read_page(
-/*==========*/
- ulint space, /*!< in: space id */
- ulint zip_size,/*!< in: compressed page size in bytes, or 0 */
- ulint offset, /*!< in: page number */
+ const page_id_t& page_id,
+ const page_size_t& page_size,
buf_page_t** bpage) /*!< out: page */
{
- ib_int64_t tablespace_version;
ulint count;
dberr_t err;
- tablespace_version = fil_space_get_version(space);
+ /* We do synchronous IO because our AIO completion code
+ is sub-optimal. See buf_page_io_complete(), we have to
+ acquire the buffer pool mutex before acquiring the block
+ mutex, required for updating the page state. The acquire
+ of the buffer pool mutex becomes an expensive bottleneck. */
- /* We do the i/o in the synchronous aio mode to save thread
- switches: hence TRUE */
+ count = buf_read_page_low(
+ &err, true,
+ 0, BUF_READ_ANY_PAGE, page_id, page_size, false, bpage);
- count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
- zip_size, FALSE,
- tablespace_version, offset, bpage);
srv_stats.buf_pool_reads.add(count);
+
if (err == DB_TABLESPACE_DELETED) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: trying to access"
- " tablespace %lu page no. %lu,\n"
- "InnoDB: but the tablespace does not exist"
- " or is just being dropped.\n",
- (ulong) space, (ulong) offset);
+ ib::error() << "trying to read page " << page_id
+ << " in nonexisting or being-dropped tablespace";
}
/* Increment number of I/O operations used for LRU policy. */
@@ -439,37 +438,30 @@ buf_read_page(
return(count > 0);
}
-/********************************************************************//**
-High-level function which reads a page asynchronously from a file to the
+/** High-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
+@param[in] page_id page id
+@param[in] page_size page size
+@param[in] sync true if synchronous aio is desired
@return TRUE if page has been read in, FALSE in case of failure */
-UNIV_INTERN
ibool
-buf_read_page_async(
-/*================*/
- ulint space, /*!< in: space id */
- ulint offset) /*!< in: page number */
+buf_read_page_background(
+ const page_id_t& page_id,
+ const page_size_t& page_size,
+ bool sync)
{
- ulint zip_size;
- ib_int64_t tablespace_version;
ulint count;
dberr_t err;
+ buf_page_t* rbpage = NULL;
- zip_size = fil_space_get_zip_size(space);
+ count = buf_read_page_low(
+ &err, sync,
+ IORequest::DO_NOT_WAKE | IORequest::IGNORE_MISSING,
+ BUF_READ_ANY_PAGE,
+ page_id, page_size, false, &rbpage);
- if (zip_size == ULINT_UNDEFINED) {
- return(FALSE);
- }
-
- tablespace_version = fil_space_get_version(space);
-
- count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE
- | OS_AIO_SIMULATED_WAKE_LATER
- | BUF_READ_IGNORE_NONEXISTENT_PAGES,
- space, zip_size, FALSE,
- tablespace_version, offset, NULL);
srv_stats.buf_pool_reads.add(count);
/* We do not increment number of I/O operations used for LRU policy
@@ -482,8 +474,7 @@ buf_read_page_async(
return(count > 0);
}
-/********************************************************************//**
-Applies linear read-ahead if in the buf_pool the page is a border page of
+/** Applies linear read-ahead if in the buf_pool the page is a border page of
a linear read-ahead area and all the pages in the area have been accessed.
Does not read any page if the read-ahead mechanism is not activated. Note
that the algorithm looks at the 'natural' adjacent successor and
@@ -505,28 +496,25 @@ latches!
NOTE 3: the calling thread must want access to the page given: this rule is
set to prevent unintended read-aheads performed by ibuf routines, a situation
which could result in a deadlock if the OS does not support asynchronous io.
-@return number of page read requests issued */
-UNIV_INTERN
+@param[in] page_id page id; see NOTE 3 above
+@param[in] page_size page size
+@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@return number of page read requests issued */
ulint
buf_read_ahead_linear(
-/*==================*/
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in bytes, or 0 */
- ulint offset, /*!< in: page number; see NOTE 3 above */
- ibool inside_ibuf) /*!< in: TRUE if we are inside ibuf routine */
+ const page_id_t& page_id,
+ const page_size_t& page_size,
+ ibool inside_ibuf)
{
- buf_pool_t* buf_pool = buf_pool_get(space, offset);
- ib_int64_t tablespace_version;
+ buf_pool_t* buf_pool = buf_pool_get(page_id);
buf_page_t* bpage;
buf_frame_t* frame;
buf_page_t* pred_bpage = NULL;
ulint pred_offset;
ulint succ_offset;
- ulint count;
int asc_or_desc;
ulint new_offset;
ulint fail_count;
- ulint ibuf_mode;
ulint low, high;
dberr_t err;
ulint i;
@@ -539,24 +527,23 @@ buf_read_ahead_linear(
return(0);
}
- if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
+ if (srv_startup_is_before_trx_rollback_phase) {
/* No read-ahead to avoid thread deadlocks */
return(0);
}
- low = (offset / buf_read_ahead_linear_area)
+ low = (page_id.page_no() / buf_read_ahead_linear_area)
* buf_read_ahead_linear_area;
- high = (offset / buf_read_ahead_linear_area + 1)
+ high = (page_id.page_no() / buf_read_ahead_linear_area + 1)
* buf_read_ahead_linear_area;
- if ((offset != low) && (offset != high - 1)) {
+ if ((page_id.page_no() != low) && (page_id.page_no() != high - 1)) {
/* This is not a border page of the area: return */
return(0);
}
- if (ibuf_bitmap_page(zip_size, offset)
- || trx_sys_hdr_page(space, offset)) {
+ if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
@@ -568,18 +555,22 @@ buf_read_ahead_linear(
/* Remember the tablespace version before we ask te tablespace size
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
do not try to read outside the bounds of the tablespace! */
+ ulint space_size;
- tablespace_version = fil_space_get_version(space);
-
- buf_pool_mutex_enter(buf_pool);
-
- if (high > fil_space_get_size(space)) {
- buf_pool_mutex_exit(buf_pool);
- /* The area is not whole, return */
+ if (fil_space_t* space = fil_space_acquire(page_id.space())) {
+ space_size = space->size;
+ fil_space_release(space);
+ if (high > space_size) {
+ /* The area is not whole */
+ return(0);
+ }
+ } else {
return(0);
}
+ buf_pool_mutex_enter(buf_pool);
+
if (buf_pool->n_pend_reads
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
buf_pool_mutex_exit(buf_pool);
@@ -593,19 +584,20 @@ buf_read_ahead_linear(
asc_or_desc = 1;
- if (offset == low) {
+ if (page_id.page_no() == low) {
asc_or_desc = -1;
}
/* How many out of order accessed pages can we ignore
when working out the access pattern for linear readahead */
- threshold = ut_min((64 - srv_read_ahead_threshold),
+ threshold = ut_min(static_cast<ulint>(64 - srv_read_ahead_threshold),
BUF_READ_AHEAD_AREA(buf_pool));
fail_count = 0;
for (i = low; i < high; i++) {
- bpage = buf_page_hash_get(buf_pool, space, i);
+ bpage = buf_page_hash_get(buf_pool,
+ page_id_t(page_id.space(), i));
if (bpage == NULL || !buf_page_is_accessed(bpage)) {
/* Not accessed */
@@ -643,7 +635,7 @@ buf_read_ahead_linear(
/* If we got this far, we know that enough pages in the area have
been accessed in the right order: linear read-ahead can be sensible */
- bpage = buf_page_hash_get(buf_pool, space, offset);
+ bpage = buf_page_hash_get(buf_pool, page_id);
if (bpage == NULL) {
buf_pool_mutex_exit(buf_pool);
@@ -674,12 +666,14 @@ buf_read_ahead_linear(
buf_pool_mutex_exit(buf_pool);
- if ((offset == low) && (succ_offset == offset + 1)) {
+ if ((page_id.page_no() == low)
+ && (succ_offset == page_id.page_no() + 1)) {
/* This is ok, we can continue */
new_offset = pred_offset;
- } else if ((offset == high - 1) && (pred_offset == offset - 1)) {
+ } else if ((page_id.page_no() == high - 1)
+ && (pred_offset == page_id.page_no() - 1)) {
/* This is ok, we can continue */
new_offset = succ_offset;
@@ -700,19 +694,19 @@ buf_read_ahead_linear(
return(0);
}
- if (high > fil_space_get_size(space)) {
+ if (high > space_size) {
/* The area is not whole, return */
return(0);
}
+ ulint count = 0;
+
/* If we got this far, read-ahead can be sensible: do it */
- ibuf_mode = inside_ibuf
- ? BUF_READ_IBUF_PAGES_ONLY | OS_AIO_SIMULATED_WAKE_LATER
- : BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER;
+ ulint ibuf_mode;
- count = 0;
+ ibuf_mode = inside_ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE;
/* Since Windows XP seems to schedule the i/o handler thread
very eagerly, and consequently it does not wait for the
@@ -724,20 +718,22 @@ buf_read_ahead_linear(
/* It is only sensible to do read-ahead in the non-sync
aio mode: hence FALSE as the first parameter */
- if (!ibuf_bitmap_page(zip_size, i)) {
+ const page_id_t cur_page_id(page_id.space(), i);
+
+ if (!ibuf_bitmap_page(cur_page_id, page_size)) {
+ buf_page_t* rpage = NULL;
+
count += buf_read_page_low(
&err, false,
- ibuf_mode,
- space, zip_size, FALSE, tablespace_version, i, NULL);
+ IORequest::DO_NOT_WAKE,
+ ibuf_mode, cur_page_id, page_size, false, &rpage);
+
if (err == DB_TABLESPACE_DELETED) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Warning: in"
- " linear readahead trying to access\n"
- "InnoDB: tablespace %lu page %lu,\n"
- "InnoDB: but the tablespace does not"
- " exist or is just being dropped.\n",
- (ulong) space, (ulong) i);
+ ib::warn() << "linear readahead trying to"
+ " access page "
+ << page_id_t(page_id.space(), i)
+ << " in nonexisting or being-dropped"
+ " tablespace";
}
}
}
@@ -748,13 +744,13 @@ buf_read_ahead_linear(
os_aio_simulated_wake_handler_threads();
-#ifdef UNIV_DEBUG
- if (buf_debug_prints && (count > 0)) {
- fprintf(stderr,
- "LINEAR read-ahead space %lu offset %lu pages %lu\n",
- (ulong) space, (ulong) offset, (ulong) count);
+ if (count) {
+ DBUG_PRINT("ib_buf", ("linear read-ahead %lu pages, "
+ UINT32PF ":" UINT32PF,
+ count,
+ page_id.space(),
+ page_id.page_no()));
}
-#endif /* UNIV_DEBUG */
/* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */
@@ -768,7 +764,6 @@ buf_read_ahead_linear(
Issues read requests for pages which the ibuf module wants to read in, in
order to contract the insert buffer tree. Technically, this function is like
a read-ahead function. */
-UNIV_INTERN
void
buf_read_ibuf_merge_pages(
/*======================*/
@@ -778,7 +773,7 @@ buf_read_ibuf_merge_pages(
to get read in, before this
function returns */
const ulint* space_ids, /*!< in: array of space ids */
- const ib_int64_t* space_versions,/*!< in: the spaces must have
+ const ib_uint64_t* space_versions,/*!< in: the spaces must have
this version number
(timestamp), otherwise we
discard the read; we use this
@@ -792,100 +787,94 @@ buf_read_ibuf_merge_pages(
ulint n_stored) /*!< in: number of elements
in the arrays */
{
- ulint i;
-
#ifdef UNIV_IBUF_DEBUG
ut_a(n_stored < UNIV_PAGE_SIZE);
#endif
- for (i = 0; i < n_stored; i++) {
- dberr_t err;
- buf_pool_t* buf_pool;
- ulint zip_size = fil_space_get_zip_size(space_ids[i]);
+ for (ulint i = 0; i < n_stored; i++) {
+ const page_id_t page_id(space_ids[i], page_nos[i]);
+
+ buf_pool_t* buf_pool = buf_pool_get(page_id);
+ buf_page_t* rpage = NULL;
- buf_pool = buf_pool_get(space_ids[i], page_nos[i]);
+ bool found;
+ const page_size_t page_size(fil_space_get_page_size(
+ space_ids[i], &found));
+
+ if (!found) {
+ /* The tablespace was not found, remove the
+ entries for that page */
+ ibuf_merge_or_delete_for_page(NULL, page_id,
+ NULL, FALSE);
+ continue;
+ }
while (buf_pool->n_pend_reads
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
os_thread_sleep(500000);
}
- if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
+ dberr_t err;
- goto tablespace_deleted;
- }
+ buf_read_page_low(&err,
+ sync && (i + 1 == n_stored),
+ 0,
+ BUF_READ_ANY_PAGE, page_id, page_size,
+ true, &rpage);
- buf_read_page_low(&err, sync && (i + 1 == n_stored),
- BUF_READ_ANY_PAGE, space_ids[i],
- zip_size, TRUE, space_versions[i],
- page_nos[i], NULL);
-
- if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
-tablespace_deleted:
+ if (err == DB_TABLESPACE_DELETED) {
/* We have deleted or are deleting the single-table
tablespace: remove the entries for that page */
-
- ibuf_merge_or_delete_for_page(NULL, space_ids[i],
- page_nos[i],
- zip_size, FALSE);
+ ibuf_merge_or_delete_for_page(NULL, page_id,
+ &page_size, FALSE);
}
}
os_aio_simulated_wake_handler_threads();
-#ifdef UNIV_DEBUG
- if (buf_debug_prints) {
- fprintf(stderr,
- "Ibuf merge read-ahead space %lu pages %lu\n",
- (ulong) space_ids[0], (ulong) n_stored);
+ if (n_stored) {
+ DBUG_PRINT("ib_buf",
+ ("ibuf merge read-ahead %u pages, space %u",
+ unsigned(n_stored), unsigned(space_ids[0])));
}
-#endif /* UNIV_DEBUG */
}
-/********************************************************************//**
-Issues read requests for pages which recovery wants to read in. */
-UNIV_INTERN
+/** Issues read requests for pages which recovery wants to read in.
+@param[in] sync true if the caller wants this function to wait
+for the highest address page to get read in, before this function returns
+@param[in] space_id tablespace id
+@param[in] page_nos array of page numbers to read, with the
+highest page number the last in the array
+@param[in] n_stored number of page numbers in the array */
void
buf_read_recv_pages(
-/*================*/
- ibool sync, /*!< in: TRUE if the caller
- wants this function to wait
- for the highest address page
- to get read in, before this
- function returns */
- ulint space, /*!< in: space id */
- ulint zip_size, /*!< in: compressed page size in
- bytes, or 0 */
- const ulint* page_nos, /*!< in: array of page numbers
- to read, with the highest page
- number the last in the
- array */
- ulint n_stored) /*!< in: number of page numbers
- in the array */
+ bool sync,
+ ulint space_id,
+ const ulint* page_nos,
+ ulint n_stored)
{
- ib_int64_t tablespace_version;
- ulint count;
- dberr_t err;
- ulint i;
-
- zip_size = fil_space_get_zip_size(space);
-
- if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
- /* It is a single table tablespace and the .ibd file is
- missing: do nothing */
+ ulint count;
+ dberr_t err;
+ ulint i;
+ fil_space_t* space = fil_space_get(space_id);
+ if (space == NULL) {
+ /* The tablespace is missing: do nothing */
return;
}
- tablespace_version = fil_space_get_version(space);
+ fil_space_open_if_needed(space);
+
+ const page_size_t page_size(space->flags);
for (i = 0; i < n_stored; i++) {
- buf_pool_t* buf_pool;
+ buf_pool_t* buf_pool;
+ const page_id_t cur_page_id(space_id, page_nos[i]);
+ buf_page_t* rpage = NULL;
count = 0;
- os_aio_print_debug = FALSE;
- buf_pool = buf_pool_get(space, page_nos[i]);
+ buf_pool = buf_pool_get(cur_page_id);
while (buf_pool->n_pend_reads >= recv_n_pool_free_frames / 2) {
os_aio_simulated_wake_handler_threads();
@@ -893,42 +882,34 @@ buf_read_recv_pages(
count++;
- if (count > 1000) {
- fprintf(stderr,
- "InnoDB: Error: InnoDB has waited for"
- " 10 seconds for pending\n"
- "InnoDB: reads to the buffer pool to"
- " be finished.\n"
- "InnoDB: Number of pending reads %lu,"
- " pending pread calls %lu\n",
- (ulong) buf_pool->n_pend_reads,
- (ulong) os_file_n_pending_preads);
-
- os_aio_print_debug = TRUE;
+ if (!(count % 1000)) {
+
+ ib::error()
+ << "Waited for " << count / 100
+ << " seconds for "
+ << buf_pool->n_pend_reads
+ << " pending reads";
}
}
- os_aio_print_debug = FALSE;
-
if ((i + 1 == n_stored) && sync) {
- buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space,
- zip_size, TRUE, tablespace_version,
- page_nos[i], NULL);
+ buf_read_page_low(
+ &err, true,
+ 0,
+ BUF_READ_ANY_PAGE,
+ cur_page_id, page_size, true, &rpage);
} else {
- buf_read_page_low(&err, false, BUF_READ_ANY_PAGE
- | OS_AIO_SIMULATED_WAKE_LATER,
- space, zip_size, TRUE,
- tablespace_version, page_nos[i], NULL);
+ buf_read_page_low(
+ &err, false,
+ IORequest::DO_NOT_WAKE,
+ BUF_READ_ANY_PAGE,
+ cur_page_id, page_size, true, &rpage);
}
}
os_aio_simulated_wake_handler_threads();
-#ifdef UNIV_DEBUG
- if (buf_debug_prints) {
- fprintf(stderr,
- "Recovery applies read-ahead pages %lu\n",
- (ulong) n_stored);
- }
-#endif /* UNIV_DEBUG */
+ DBUG_PRINT("ib_buf", ("recovery read-ahead (%u pages)",
+ unsigned(n_stored)));
}
+