函数buf_page_get_gen
/********************************************************************//**
This is the general function used to get access to a database page.
@return pointer to the block or NULL */
UNIV_INTERN
buf_block_t*
buf_page_get_gen(
/*=============*/
ulint space, /*!< in: space id */
ulint zip_size,/*!< in: compressed page size in bytes
or 0 for uncompressed pages */
ulint offset, /*!< in: page number */
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */
buf_block_t* guess, /*!< in: guessed block or NULL */
ulint mode, /*!< in: BUF_GET, BUF_GET_IF_IN_POOL,
BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or
BUF_GET_IF_IN_POOL_OR_WATCH */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mini-transaction */
{
buf_block_t* block;
ulint fold;
unsigned access_time;
ulint fix_type;
ibool must_read;
ulint retries = ;
buf_pool_t* buf_pool = buf_pool_get(space, offset);
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_NO_LATCH));
ut_ad(zip_size == fil_space_get_zip_size(space));
ut_ad(ut_is_2pow(zip_size));
buf_pool->stat.n_page_gets++;
fold = buf_page_address_fold(space, offset);
loop:
block = guess; //guess 为 NULL
buf_pool_mutex_enter(buf_pool);
if (block) { //这里不进来,因为block为空
/* If the guess is a compressed page descriptor that
has been allocated by buf_page_alloc_descriptor(),
it may have been freed by buf_relocate(). */
if (!buf_block_is_uncompressed(buf_pool, block)
|| offset != block->page.offset
|| space != block->page.space
|| buf_block_get_state(block) != BUF_BLOCK_FILE_PAGE) {
block = guess = NULL;
} else {
ut_ad(!block->page.in_zip_hash);
ut_ad(block->page.in_page_hash);
}
}
if (block == NULL) { /** *详见 *从buf_pool->page_hash中找到相应page *当找到的page->offset == offset时,返回page * */
block = (buf_block_t*) buf_page_hash_get_low(buf_pool, space, offset, fold);
}
if (block && buf_pool_watch_is_sentinel(buf_pool, &block->page)) {
block = NULL;
}
if (block == NULL) {
/* Page not in buf_pool: needs to be read from file */
//如果hash表中没有找到block,就读取硬盘文件
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
block = (buf_block_t*) buf_pool_watch_set(space, offset, fold);
if (UNIV_LIKELY_NULL(block)) {
goto got_block;
}
}
buf_pool_mutex_exit(buf_pool);
if (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_PEEK_IF_IN_POOL
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
return(NULL);
}
if (buf_read_page(space, zip_size, offset)) {//从硬盘中读取数据,并开始预读,详见
buf_read_ahead_random(space, zip_size, offset,ibuf_inside(mtr));
retries = ;
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries;
DBUG_EXECUTE_IF(
"innodb_page_corruption_retries",
retries = BUF_PAGE_READ_MAX_RETRIES;
);
} else {
fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no"
" %lu into the buffer pool after"
" %lu attempts\n"
"InnoDB: The most probable cause"
" of this error may be that the"
" table has been corrupted.\n"
"InnoDB: You can try to fix this"
" problem by using"
" innodb_force_recovery.\n"
"InnoDB: Please see reference manual"
" for more details.\n"
"InnoDB: Aborting...\n",
space, offset,
BUF_PAGE_READ_MAX_RETRIES);
ut_error;
}
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % || buf_validate());
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
goto loop;
}
got_block:
ut_ad(page_zip_get_size(&block->page.zip) == zip_size);
must_read = buf_block_get_io_fix(block) == BUF_IO_READ;
if (must_read && (mode == BUF_GET_IF_IN_POOL
|| mode == BUF_PEEK_IF_IN_POOL)) {
/* The page is being read to buffer pool,
but we cannot wait around for the read to
complete. */
null_exit:
buf_pool_mutex_exit(buf_pool);
return(NULL);
}
switch (buf_block_get_state(block)) {
buf_page_t* bpage;
ibool success;
case BUF_BLOCK_FILE_PAGE:
break;
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
if (mode == BUF_PEEK_IF_IN_POOL) {
/* This mode is only used for dropping an
adaptive hash index. There cannot be an
adaptive hash index for a compressed-only
page, so do not bother decompressing the page. */
goto null_exit;
}
bpage = &block->page;
/* Protect bpage->buf_fix_count. */
mutex_enter(&buf_pool->zip_mutex);
if (bpage->buf_fix_count
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
/* This condition often occurs when the buffer
is not buffer-fixed, but I/O-fixed by
buf_page_init_for_read(). */
mutex_exit(&buf_pool->zip_mutex);
wait_until_unfixed:
/* The block is buffer-fixed or I/O-fixed.
Try again later. */
buf_pool_mutex_exit(buf_pool);
os_thread_sleep(WAIT_FOR_READ);
goto loop;
}
/* Buffer-fix the block so that it cannot be evicted
or relocated while we are attempting to allocate an
uncompressed page. */
bpage->buf_fix_count++;
/* Allocate an uncompressed page. */
buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_mutex);
block = buf_LRU_get_free_block(buf_pool);
ut_a(block);
buf_pool_mutex_enter(buf_pool);
mutex_enter(&block->mutex);
mutex_enter(&buf_pool->zip_mutex);
/* Buffer-fixing prevents the page_hash from changing. */
ut_ad(bpage == buf_page_hash_get_low(buf_pool,
space, offset, fold));
if (--bpage->buf_fix_count
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
mutex_exit(&buf_pool->zip_mutex);
/* The block was buffer-fixed or I/O-fixed while
buf_pool->mutex was not held by this thread.
Free the block that was allocated and retry.
This should be extremely unlikely, for example,
if buf_page_get_zip() was invoked. */
buf_LRU_block_free_non_file_page(block);
mutex_exit(&block->mutex);
goto wait_until_unfixed;
}
/* Move the compressed page from bpage to block,
and uncompress it. */
buf_relocate(bpage, &block->page);
buf_block_init_low(block);
block->lock_hash_val = lock_rec_hash(space, offset);
UNIV_MEM_DESC(&block->page.zip.data,
page_zip_get_size(&block->page.zip), block);
if (buf_page_get_state(&block->page)
== BUF_BLOCK_ZIP_PAGE) {
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(list, buf_pool->zip_clean,
&block->page);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
ut_ad(!block->page.in_flush_list);
} else {
/* Relocate buf_pool->flush_list. */
buf_flush_relocate_on_flush_list(bpage,
&block->page);
}
/* Buffer-fix, I/O-fix, and X-latch the block
for the duration of the decompression.
Also add the block to the unzip_LRU list. */
block->page.state = BUF_BLOCK_FILE_PAGE;
/* Insert at the front of unzip_LRU list */
buf_unzip_LRU_add_block(block, FALSE);
block->page.buf_fix_count = ;
buf_block_set_io_fix(block, BUF_IO_READ);
rw_lock_x_lock_inline(&block->, file, line);
UNIV_MEM_INVALID(bpage, sizeof *bpage);
buf_pool->n_pend_unzip++;
mutex_exit(&buf_pool->zip_mutex);
buf_pool_mutex_exit(buf_pool);
access_time = buf_page_is_accessed(&block->page);
mutex_exit(&block->mutex);
buf_page_free_descriptor(bpage);
/* Decompress the page while not holding
buf_pool->mutex or block->mutex. */
success = buf_zip_decompress(block, srv_use_checksums);
ut_a(success);
if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
if (access_time) {
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(space, offset) == );
#endif /* UNIV_IBUF_COUNT_DEBUG */
} else {
ibuf_merge_or_delete_for_page(
block, space, offset, zip_size, TRUE);
}
}
/* Unfix and unlatch the block. */
buf_pool_mutex_enter(buf_pool);
mutex_enter(&block->mutex);
block->page.buf_fix_count--;
buf_block_set_io_fix(block, BUF_IO_NONE);
mutex_exit(&block->mutex);
buf_pool->n_pend_unzip--;
rw_lock_x_unlock(&block->lock);
break;
case BUF_BLOCK_ZIP_FREE:
case BUF_BLOCK_NOT_USED:
case BUF_BLOCK_READY_FOR_USE:
case BUF_BLOCK_MEMORY:
case BUF_BLOCK_REMOVE_HASH:
ut_error;
break;
}
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
mutex_enter(&block->mutex);
#if UNIV_WORD_SIZE == 4
/* On 32-bit systems, there is no padding in buf_page_t. On
other systems, Valgrind could complain about uninitialized pad
bytes. */
UNIV_MEM_ASSERT_RW(&block->page, sizeof block->page);
#endif
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
if ((mode == BUF_GET_IF_IN_POOL || mode == BUF_GET_IF_IN_POOL_OR_WATCH)
&& ibuf_debug) {
/* Try to evict the block from the buffer pool, to use the
insert buffer (change buffer) as much as possible. */
if (buf_LRU_free_block(&block->page, TRUE)) {
mutex_exit(&block->mutex);
if (mode == BUF_GET_IF_IN_POOL_OR_WATCH) {
/* Set the watch, as it would have
been set if the page were not in the
buffer pool in the first place. */
block = (buf_block_t*) buf_pool_watch_set(
space, offset, fold);
if (UNIV_LIKELY_NULL(block)) {
/* The page entered the buffer
pool for some reason. Try to
evict it again. */
goto got_block;
}
}
buf_pool_mutex_exit(buf_pool);
fprintf(stderr,
"innodb_change_buffering_debug evict %u %u\n",
(unsigned) space, (unsigned) offset);
return(NULL);
} else if (buf_flush_page_try(buf_pool, block)) {
fprintf(stderr,
"innodb_change_buffering_debug flush %u %u\n",
(unsigned) space, (unsigned) offset);
guess = block;
goto loop;
}
/* Failed to evict the page; change it directly */
}
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
buf_block_buf_fix_inc(block, file, line);
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
ut_a(mode == BUF_GET_POSSIBLY_FREED
|| !block->page.file_page_was_freed);
#endif
buf_pool_mutex_exit(buf_pool);
/* Check if this is the first access to the page */
access_time = buf_page_is_accessed(&block->page);
buf_page_set_accessed(&block->page);
mutex_exit(&block->mutex);
if (mode != BUF_PEEK_IF_IN_POOL) {
buf_page_make_young_if_needed(&block->page);
}
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % || buf_validate());
ut_a(block->page.buf_fix_count > );
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
switch (rw_latch) {
case RW_NO_LATCH:
if (must_read) {
/* Let us wait until the read operation
completes */
for (;;) {
enum buf_io_fix io_fix;
mutex_enter(&block->mutex);
io_fix = buf_block_get_io_fix(block);
mutex_exit(&block->mutex);
if (io_fix == BUF_IO_READ) {
/* wait by temporaly s-latch */
rw_lock_s_lock(&(block->lock));
rw_lock_s_unlock(&(block->lock));
} else {
break;
}
}
}
fix_type = MTR_MEMO_BUF_FIX;
break;
case RW_S_LATCH:
rw_lock_s_lock_inline(&(block->, file, line);
fix_type = MTR_MEMO_PAGE_S_FIX;
break;
default:
ut_ad(rw_latch == RW_X_LATCH);
rw_lock_x_lock_inline(&(block->, file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
break;
}
mtr_memo_push(mtr, block, fix_type);
if (mode != BUF_PEEK_IF_IN_POOL && !access_time) {
/* In the case of a first access, try to apply linear
read-ahead */
buf_read_ahead_linear(space, zip_size, offset,
ibuf_inside(mtr));
}
#ifdef UNIV_IBUF_COUNT_DEBUG
ut_a(ibuf_count_get(buf_block_get_space(block),
buf_block_get_page_no(block)) == );
#endif
return(block);
}
函数buf_page_get_gen的更多相关文章
- Python 小而美的函数
python提供了一些有趣且实用的函数,如any all zip,这些函数能够大幅简化我们得代码,可以更优雅的处理可迭代的对象,同时使用的时候也得注意一些情况 any any(iterable) ...
- 探究javascript对象和数组的异同,及函数变量缓存技巧
javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...
- JavaScript权威指南 - 函数
函数本身就是一段JavaScript代码,定义一次但可能被调用任意次.如果函数挂载在一个对象上,作为对象的一个属性,通常这种函数被称作对象的方法.用于初始化一个新创建的对象的函数被称作构造函数. 相对 ...
- C++对C的函数拓展
一,内联函数 1.内联函数的概念 C++中的const常量可以用来代替宏常数的定义,例如:用const int a = 10来替换# define a 10.那么C++中是否有什么解决方案来替代宏代码 ...
- 菜鸟Python学习笔记第一天:关于一些函数库的使用
2017年1月3日 星期二 大一学习一门新的计算机语言真的很难,有时候连函数拼写出错查错都能查半天,没办法,谁让我英语太渣. 关于计算机语言的学习我想还是从C语言学习开始为好,Python有很多语言的 ...
- javascript中的this与函数讲解
前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...
- 复杂的 Hash 函数组合有意义吗?
很久以前看到一篇文章,讲某个大网站储存用户口令时,会经过十分复杂的处理.怎么个复杂记不得了,大概就是先 Hash,结果加上一些特殊字符再 Hash,结果再加上些字符.再倒序.再怎么怎么的.再 Hash ...
- JS核心系列:浅谈函数的作用域
一.作用域(scope) 所谓作用域就是:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的. function scope(){ var foo = "global&quo ...
- C++中的时间函数
C++获取时间函数众多,何时该用什么函数,拿到的是什么时间?该怎么用?很多人都会混淆. 本文是本人经历了几款游戏客户端和服务器开发后,对游戏中时间获取的一点总结. 最早学习游戏客户端时,为了获取最精确 ...
随机推荐
- SSMS 2008R2没有智能感知方法解决
有时SSMS会莫明奇妙的没有了智能感知(前一天还是有的, 第2天就没有了) 在网上查到有如下原因: 1. 服务器上有Offline的DB 解决方案: 将Offline的DB删掉或者设成online即可 ...
- 把NodeJS注册成Windows服务
为了让NodeJS开发的网站能在服务器端正常运行,最好把NodeJS需要运行的代码注册成Windows服务,服务器如果重启也不需要重新去启动NodeJS. 1.编写一个执行NodeJS脚本的bat文件 ...
- SecureCRT配色方案
SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单地说是Windows下登录UNIX或Linux服务器主机的软件.作为一款经常使用的终端软件,一个好的配色方案可以大大的提高学 ...
- Java7 新特性 数值文本表示法
今天和大家分享下 java7中新特性-数值文本表示法 首先,在原来jdk1.6中 如果需要将一个二进制的数值转换成十进制的话,一般情况下都会以下面的代码方式去实现. public static voi ...
- Android工具包
Eclipse + ADT +SDK,下载ADT Bundle全包含 adt-bundle-windows-x86_64-20140702 http://www.cnblogs.com/tc310/p ...
- [转载]App.Config详解及读写操作
App.Config详解 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序.配置文件的根节点是c ...
- 从String类看写C++ class需要注意的地方
#include <iostream> #include <string.h> using namespace std; class String { char* m_data ...
- int a[5]={1,2,3,4,5}; int *p=(int*)(&a+1); printf("%d",*(p-1)); 答案为什么是5?
这个问题的关键是理解 &a a是一个数组名,也就是数组的首地址.对a进行取地址运算符,得到的是一个指向数组的指针!!!!这句话尤为重要!也就相当于int (*p) [5] = &a;p ...
- uva 434
贪心 ~ #include <cstdio> #include <cstdlib> #include <cmath> #include <map> #i ...
- React vs Angular 2: 冰与火之歌
黄玄 · 3 个月前 本文译自 Angular 2 versus React: There Will Be Blood ,其实之前有人翻译过,但是翻得水平有一点不忍直视,我们不希望浪费这篇好文章. 本 ...