/********************************************************************//**
Function which inits a page for read to the buffer buf_pool. If the page is
(1) already in buf_pool, or
(2) if we specify to read only ibuf pages and the page is not an ibuf page, or
(3) if the space is deleted or being deleted,
then this function does nothing.
Sets the io_fix flag to BUF_IO_READ and sets a non-recursive exclusive lock
on the buffer frame. The io-handler must take care that the flag is cleared
and the lock released later.
@return    pointer to the block or NULL */
UNIV_INTERN
buf_page_t*
buf_page_init_for_read(
/*===================*/
    ulint*        err,    /*!< out: DB_SUCCESS or DB_TABLESPACE_DELETED */
    ulint        mode,    /*!< in: BUF_READ_IBUF_PAGES_ONLY, ... */
    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: prevents reading from a wrong
                version of the tablespace in case we have done
                DISCARD + IMPORT */
    ulint        offset)    /*!< in: page number */
{
    buf_block_t*    block;
    buf_page_t*    bpage    = NULL;
    buf_page_t*    watch_page;
    mtr_t        mtr;
    ulint        fold;
    ibool        lru    = FALSE;
    void*        data;
    buf_pool_t*    buf_pool = buf_pool_get(space, offset);

    ut_ad(buf_pool);

    *err = DB_SUCCESS;

    if (mode == BUF_READ_IBUF_PAGES_ONLY) {
        /* It is a read-ahead within an ibuf routine */

        ut_ad(!ibuf_bitmap_page(zip_size, offset));

        ibuf_mtr_start(&mtr);

        if (!recv_no_ibuf_operations
            && !ibuf_page(space, zip_size, offset, &mtr)) {

            ibuf_mtr_commit(&mtr);

            return(NULL);
        }
    } else {
        ut_ad(mode == BUF_READ_ANY_PAGE);
    }

    if (zip_size && UNIV_LIKELY(!unzip)
        && UNIV_LIKELY(!recv_recovery_is_on())) {
        block = NULL;
    } else {        /**         *按理说 会走到这里  zip_size 为0 ,非压缩页         *         *         */
        block = buf_LRU_get_free_block(buf_pool); //获得一块余闲的block free_list->uzip_lru->common_lru顺序 详见
        ut_ad(block);
        ut_ad(buf_pool_from_block(block) == buf_pool);
    }

    fold = buf_page_address_fold(space, offset);

    buf_pool_mutex_enter(buf_pool);

    watch_page = buf_page_hash_get_low(buf_pool, space, offset, fold);
    if (watch_page && !buf_pool_watch_is_sentinel(buf_pool, watch_page)) {
        /* The page is already in the buffer pool. */
        watch_page = NULL;
err_exit:
        if (block) {
            mutex_enter(&block->mutex);
            buf_LRU_block_free_non_file_page(block);
            mutex_exit(&block->mutex);
        }

        bpage = NULL;
        goto func_exit;
    }

    if (fil_tablespace_deleted_or_being_deleted_in_mem(
            space, tablespace_version)) {
        /* The page belongs to a space which has been
        deleted or is being deleted. */
        *err = DB_TABLESPACE_DELETED;

        goto err_exit;
    }

    if (block) {
        bpage = &block->page;
        mutex_enter(&block->mutex);

        ut_ad(buf_pool_from_bpage(bpage) == buf_pool);

        buf_page_init(buf_pool, space, offset, fold, zip_size, block); //详见        /* The block must be put to the LRU list, to the old blocks */
        buf_LRU_add_block(bpage, TRUE/* to old blocks */);

        /* We set a pass-type x-lock on the frame because then
        the same thread which called for the read operation
        (and is running now at this point of code) can wait
        for the read to complete by waiting for the x-lock on
        the frame; if the x-lock were recursive, the same
        thread would illegally get the x-lock before the page
        read is completed.  The x-lock is cleared by the
        io-handler thread. */

        rw_lock_x_lock_gen(&block->lock, BUF_IO_READ);
        buf_page_set_io_fix(bpage, BUF_IO_READ);//设置bpage->io_fix为BUF_IO_READ,表示将从磁盘读取Page

        if (UNIV_UNLIKELY(zip_size)) {
            /* buf_pool->mutex may be released and
            reacquired by buf_buddy_alloc().  Thus, we
            must release block->mutex in order not to
            break the latching order in the reacquisition
            of buf_pool->mutex.  We also must defer this
            operation until after the block descriptor has
            been added to buf_pool->LRU and
            buf_pool->page_hash. */
            mutex_exit(&block->mutex);
            data = buf_buddy_alloc(buf_pool, zip_size, &lru);
            mutex_enter(&block->mutex);
            block->page.zip.data = data;

            /* To maintain the invariant
            block->in_unzip_LRU_list
            == buf_page_belongs_to_unzip_LRU(&block->page)
            we have to add this block to unzip_LRU
            after block->page.zip.data is set. */
            ut_ad(buf_page_belongs_to_unzip_LRU(&block->page));
            buf_unzip_LRU_add_block(block, TRUE);
        }

        mutex_exit(&block->mutex);
    } else {
        /* The compressed page must be allocated before the
        control block (bpage), in order to avoid the
        invocation of buf_buddy_relocate_block() on
        uninitialized data. */
        data = buf_buddy_alloc(buf_pool, zip_size, &lru);

        /* If buf_buddy_alloc() allocated storage from the LRU list,
        it released and reacquired buf_pool->mutex.  Thus, we must
        check the page_hash again, as it may have been modified. */
        if (UNIV_UNLIKELY(lru)) {

            watch_page = buf_page_hash_get_low(
                buf_pool, space, offset, fold);

            if (watch_page
                && !buf_pool_watch_is_sentinel(buf_pool,
                                  watch_page)) {

                /* The block was added by some other thread. */
                watch_page = NULL;
                buf_buddy_free(buf_pool, data, zip_size);

                bpage = NULL;
                goto func_exit;
            }
        }

        bpage = buf_page_alloc_descriptor();

        /* Initialize the buf_pool pointer. */
        bpage->buf_pool_index = buf_pool_index(buf_pool);

        page_zip_des_init(&bpage->zip);
        page_zip_set_size(&bpage->zip, zip_size);
        bpage->zip.data = data;

        mutex_enter(&buf_pool->zip_mutex);
        UNIV_MEM_DESC(bpage->zip.data,
                  page_zip_get_size(&bpage->zip), bpage);

        buf_page_init_low(bpage);

        bpage->state    = BUF_BLOCK_ZIP_PAGE;
        bpage->space    = space;
        bpage->offset    = offset;

#ifdef UNIV_DEBUG
        bpage->in_page_hash = FALSE;
        bpage->in_zip_hash = FALSE;
        bpage->in_flush_list = FALSE;
        bpage->in_free_list = FALSE;
        bpage->in_LRU_list = FALSE;
#endif /* UNIV_DEBUG */

        ut_d(bpage->in_page_hash = TRUE);

        if (UNIV_LIKELY_NULL(watch_page)) {
            /* Preserve the reference count. */
            ulint    buf_fix_count = watch_page->buf_fix_count;
            ut_a(buf_fix_count > );
            bpage->buf_fix_count += buf_fix_count;
            ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
            buf_pool_watch_remove(buf_pool, fold, watch_page);
        }

        HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold,
                bpage);

        /* The block must be put to the LRU list, to the old blocks
        The zip_size is already set into the page zip */
        buf_LRU_add_block(bpage, TRUE/* to old blocks */);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
        buf_LRU_insert_zip_clean(bpage);
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */

        buf_page_set_io_fix(bpage, BUF_IO_READ);

        mutex_exit(&buf_pool->zip_mutex);
    }

    buf_pool->n_pend_reads++;
func_exit:
    buf_pool_mutex_exit(buf_pool);

    if (mode == BUF_READ_IBUF_PAGES_ONLY) {

        ibuf_mtr_commit(&mtr);
    }

    ut_ad(!bpage || buf_page_in_file(bpage));
    return(bpage);
}

函数buf_page_init_for_read的更多相关文章

  1. InnoDB源码分析--缓冲池(二)

    转载请附原文链接:http://www.cnblogs.com/wingsless/p/5578727.html 上一篇中我简单的分析了一下InnoDB缓冲池LRU算法的相关源码,其实说不上是分析,应 ...

  2. 服务器IO瓶颈对MySQL性能的影响

    [背景] 之前我们碰到一些MySQL的性能问题,比如服务器日志备份时可能会导致慢查询增多,一句简单的select或insert语句可能执行几秒,IO负载较高的服务器更容易出现并发线程数升高,CPU上升 ...

  3. Python 小而美的函数

    python提供了一些有趣且实用的函数,如any all zip,这些函数能够大幅简化我们得代码,可以更优雅的处理可迭代的对象,同时使用的时候也得注意一些情况   any any(iterable) ...

  4. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  5. JavaScript权威指南 - 函数

    函数本身就是一段JavaScript代码,定义一次但可能被调用任意次.如果函数挂载在一个对象上,作为对象的一个属性,通常这种函数被称作对象的方法.用于初始化一个新创建的对象的函数被称作构造函数. 相对 ...

  6. C++对C的函数拓展

    一,内联函数 1.内联函数的概念 C++中的const常量可以用来代替宏常数的定义,例如:用const int a = 10来替换# define a 10.那么C++中是否有什么解决方案来替代宏代码 ...

  7. 菜鸟Python学习笔记第一天:关于一些函数库的使用

    2017年1月3日 星期二 大一学习一门新的计算机语言真的很难,有时候连函数拼写出错查错都能查半天,没办法,谁让我英语太渣. 关于计算机语言的学习我想还是从C语言学习开始为好,Python有很多语言的 ...

  8. javascript中的this与函数讲解

    前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...

  9. 复杂的 Hash 函数组合有意义吗?

    很久以前看到一篇文章,讲某个大网站储存用户口令时,会经过十分复杂的处理.怎么个复杂记不得了,大概就是先 Hash,结果加上一些特殊字符再 Hash,结果再加上些字符.再倒序.再怎么怎么的.再 Hash ...

随机推荐

  1. Maven实站读后感

    这本书是一本非常经典的Maven教程,通俗易懂,同时介绍的东西十分实用,在工作上都能用到. 以前在公司里面需要要问同时的有关的Maven的问题,都可以自己解决了. 除了最基本的,以后自己可能要用到的: ...

  2. C++拷贝构造函数详解(转载)

    一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员 ...

  3. 找不到对应的webservice配置参数[ProcessService]

    在UI端 保存时 界面显示无法保存 且报此错误 “找不到对应的webservice配置参数[ProcessService]” 此下为解决方法: 首先 在[应用管理平台]--[参数模板设置] 找到你的参 ...

  4. 【技术贴】解决MySql连接不上 ip远程连接Host is not allowed to conn

    落雨 如果你想连接远程IP的mysql的时候发生这个错误: ERROR 1130: Host '192.168.1.3' is not allowed to connect to this MySQL ...

  5. 帝国cms如何调用栏目别名作为分类标题?[!--classname--]标签不能用

    用帝国cms建站安全性和生成速度会比dedecms好些,但ecms有个比较不方便的地方就是后台默认模板栏目那边没有一个seo标题设置的输入框,列表模板用的是[!--pagetitle--]标签,那么分 ...

  6. LINUX下如何查看tomcat运行状态,判断其是否启动

    1,查看Tomcat启动日志. ${catalina_home}\logs [root@iZ25b4ffkfaZ logs]# tail -f catalina.outSep 10, 2015 11: ...

  7. Android AlarmManager的取消

    取消alarm使用AlarmManager.cancel()函数,传入参数是个PendingIntent实例. 该函数会将所有跟这个PendingIntent相同的Alarm全部取消,怎么判断两者是否 ...

  8. ubuntu -LDAP的配置

    本文内容来自 http://blog.csdn.net/jl19861101/article/details/5582841 1. LDAP Server1.1. 安装主要安装一下套件: 代码: # ...

  9. BZOJ 3720 gty的妹子树

    块状树裸题 块状树: 首先对树进行分块,分出的每一块都是一个连通块 通常的分块的方式如下: 1.父亲所在块不满,分到父亲所在块中 2.父亲所在块满,自己单独开一个块 (貌似有更为优越的分块方式? 注意 ...

  10. springmvc图片上传

    //-------------------------------------上传图片--------------------------------------------------- @Requ ...