/********************************************************************//** 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. @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 */ UNIV_INTERN ulint buf_read_page_low( /*==============*/ ulint* 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 */ ibool 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 */ trx_t* trx) { buf_page_t* bpage; ulint wake_later; *err = DB_SUCCESS; wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER; if (trx_doublewrite && (space == TRX_SYS_SPACE || (srv_doublewrite_file && space == TRX_DOUBLEWRITE_SPACE)) && ( (offset >= trx_doublewrite->block1 && offset < trx_doublewrite->block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) || (offset >= trx_doublewrite->block2 && offset < trx_doublewrite->block2 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Warning: trying to read" " doublewrite buffer page %lu\n", (ulong) offset); return(0); } if (ibuf_bitmap_page(zip_size, offset) || trx_sys_hdr_page(space, offset)) { /* 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 i/o-thread. Ibuf bitmap pages must always be read with syncronous i/o, to make sure they do not get involved in thread deadlocks. */ sync = TRUE; } /* The following call will also check if the tablespace does not exist 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); if (bpage == NULL) { /* bugfix: http://bugs.mysql.com/bug.php?id=43948 */ if (recv_recovery_is_on() && *err == DB_TABLESPACE_DELETED) { /* hashed log recs must be treated here */ recv_addr_t* recv_addr; mutex_enter(&(recv_sys->mutex)); if (recv_sys->apply_log_recs == FALSE) { mutex_exit(&(recv_sys->mutex)); goto not_to_recover; } /* recv_get_fil_addr_struct() */ recv_addr = HASH_GET_FIRST(recv_sys->addr_hash, hash_calc_hash(ut_fold_ulint_pair(space, offset), recv_sys->addr_hash)); while (recv_addr) { if ((recv_addr->space == space) && (recv_addr->page_no == offset)) { break; } recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); } if ((recv_addr == NULL) || (recv_addr->state == RECV_BEING_PROCESSED) || (recv_addr->state == RECV_PROCESSED)) { mutex_exit(&(recv_sys->mutex)); goto not_to_recover; } fprintf(stderr, " (cannot find space: %lu)", space); recv_addr->state = RECV_PROCESSED; ut_a(recv_sys->n_addrs); recv_sys->n_addrs--; mutex_exit(&(recv_sys->mutex)); } not_to_recover: return(0); } #ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Posting read request for page %lu, sync %lu\n", (ulong) offset, (ulong) sync); } #endif ut_ad(buf_page_in_file(bpage)); if(sync) { thd_wait_begin(NULL, THD_WAIT_DISKIO); } if (zip_size) { *err = _fil_io(OS_FILE_READ | wake_later, sync, space, zip_size, offset, 0, zip_size, bpage->zip.data, bpage, trx); } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); *err = _fil_io(OS_FILE_READ | wake_later, sync, space, 0, offset, 0, UNIV_PAGE_SIZE, ((buf_block_t*) bpage)->frame, bpage, trx); } if (sync) { thd_wait_end(NULL); } if (*err == DB_TABLESPACE_DELETED) { buf_read_page_handle_error(bpage); return(0); } if (srv_pass_corrupt_table) { if (*err != DB_SUCCESS) { bpage->is_corrupt = TRUE; } } else { ut_a(*err == DB_SUCCESS); } if (sync) { /* The i/o is already completed when we arrive from fil_read */ if (!buf_page_io_complete(bpage)) { return(0); } } return(1); }
/********************************************************************//** 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. @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 */ static ulint buf_read_page_low( /*==============*/ ulint* 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 */ ibool 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 */ { buf_page_t* bpage; ulint wake_later; *err = DB_SUCCESS; wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER; mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER; if (trx_doublewrite && space == TRX_SYS_SPACE && ( (offset >= trx_doublewrite->block1 && offset < trx_doublewrite->block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) || (offset >= trx_doublewrite->block2 && offset < trx_doublewrite->block2 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Warning: trying to read" " doublewrite buffer page %lu\n", (ulong) offset); return(0); } if (ibuf_bitmap_page(zip_size, offset) || trx_sys_hdr_page(space, offset)) { /* 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 i/o-thread. Ibuf bitmap pages must always be read with syncronous i/o, to make sure they do not get involved in thread deadlocks. */ sync = TRUE; } /* The following call will also check if the tablespace does not exist 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); if (bpage == NULL) { return(0); } #ifdef UNIV_DEBUG if (buf_debug_prints) { fprintf(stderr, "Posting read request for page %lu, sync %lu\n", (ulong) offset, (ulong) sync); } #endif ut_ad(buf_page_in_file(bpage)); if (zip_size) { *err = fil_io(OS_FILE_READ | wake_later, sync, space, zip_size, offset, 0, zip_size, bpage->zip.data, bpage); } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); *err = fil_io(OS_FILE_READ | wake_later, sync, space, 0, offset, 0, UNIV_PAGE_SIZE, ((buf_block_t*) bpage)->frame, bpage); } ut_a(*err == DB_SUCCESS); if (sync) { /* The i/o is already completed when we arrive from fil_read */ buf_page_io_complete(bpage); } return(1); }