/********************************************************************//**
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. Cocos2D创建项目

    创建项目 配置好开发环境后, 用CMD切换到~\cocos2d\cocos2d-x-2.2.2\tools\project-creator目录上执行以下脚本 python create_project ...

  2. DRLSE 水平集算法总结

    背景: Level Set方法是美国数学家Osher(加州大学洛杉矶分校)和Sethian(加州大学伯克利分校)合作提出的.后者因为对Level Set的贡献获得了去年美国数学会与工业应用数学会联合颁 ...

  3. 文字沟通工具使用SignalR,跨域例子源代码

    其他网站已经有很多关于SignalR的介绍了.这里不多介绍. 安装:Install-Package Microsoft.AspNet.SignalR -Version 1.1.4 参考自:http:/ ...

  4. UML: CIM & PIM

    CIM-1:定义业务流程 定义及分析业务流程(Business Process)是为了尽快理清系统范围,以便估算开发成本及时间,可不是为了要改造业务流程.系统分析员千万别误解了此步骤的目的.所以,系统 ...

  5. Unix守护进程

    问题描述:         Unix守护进程 问题解决:     Unix守护进程没有控制终端,终端名设置为问号(?),终端前台进程组ID设置(TPGID)为-1 守护进程编写规则:      (1) ...

  6. NuGet使用简要说明

    引言 什么是NuGet?Nuget是 ASP .NET Gallery 的一员.NuGet 是免费.开源的包管理开发工具,专注于在 .NET 应用开发过程中,简单地合并第三方的组件库.当需要分享开发的 ...

  7. isEmpty()与equals()、==“”区别

    isEmpty方法源码:public static boolean isEmpty(String str) { return (str == null) || (str.length() == 0); ...

  8. STL中的单向队列queue

    转载自:http://blog.csdn.net/morewindows/article/details/6950917 stl中的queue指单向队列,使用时,包含头文件<queue>. ...

  9. 剑指offer--面试题5

    到现在为止,看过的书+代码有一定量了,并且也参加了个比赛,给自己的总体感觉:编程需要的是灵活的头脑,书里的东西只是讲个规则.思想,其实际实现可以千差万别!   潜在的规则+灵活的思维 = 程序! 在做 ...

  10. Eclipse 中Alt+/快捷键失效的解决办法。

    1.Eclipse下进入Windows ->Preperences ->General ->keys2.把word completion的快捷键设置alt+/删掉! 3.把Conte ...