/********************************************************************//**
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. 常见的装置与其在Linux当中的档名

    需要特别留意的是硬盘机(不论是IDE/SCSI/U盘都一样),每个磁碟机的磁盘分区(partition)不同时, 其磁碟档名还会改变呢!下一小节我们会介绍磁盘分区的相关概念啦!需要特别注意的是磁带机的 ...

  2. Error:No marked region found along edge. - Found along top edge.

    android开发的时候,初次使用.9图片出现以下: Error:No marked region found along edge. - Found along top edge. 原因: 如图:上 ...

  3. c数组与指针

    0.数组和指针并不是相同的 我们声明数组时,同时分配了一些内存空间,用于容纳数组元素,但是当我们声明一个指针时,只分配了用于容纳指针本身的内存空间. 从这个方面也可以理解sizeof后面跟数组名和指针 ...

  4. IntelliJ IDEA 比较当前版本文件与历史文件

    前言: 写代码修改后怎样比较与历史文件的区别呢?idea提供了2种比较方式(目前笔者所了解到的) 一.SVN的版本比较 二.当前文件与历史版本比较

  5. Entity Framework 基础

    在忙碌中渡过了5,6,7 月份,现在些抽点时间对Entity Framework的使用做一些基础的回忆. Entity Framework 是什么? Entity Framework(EF)和我们所熟 ...

  6. Ubuntu下非常给力的下载工具--uget+aria2

    转自Ubuntu下非常给力的下载工具--uget+aria2 Windows下的下载工具--迅雷,之所以下载速度快,乃是它能搜索资源.为己所用,而不是仅仅从原始地址这单一资源处下载. Ubuntu下也 ...

  7. c#操作剪切板

    C#定义了一个类System.Windows.Forms.Clipboard来简化剪切板操作,这个类有一个静态方法,主要有: Clear 清除剪切板中的所有数据: ContainsData,Conta ...

  8. HDU 1753 大明A+B(字符串模拟,简单题)

    简单题,但要考虑一些细节: 前导0不要,后导0不要,小数长度不一样时,有进位时,逆置处理输出 然后处理起来就比较麻烦了. 题目链接 我的代码纯模拟,把小数点前后分开来处理,写的很繁杂,纯当纪念——可怜 ...

  9. 各种实用的js,bootstrap插件

    1.nivoSlider  非常优秀的Banner轮播插件 2.BootstrapTable 表格插件使用技巧 = http://www.cnblogs.com/landeanfen/p/497683 ...

  10. PKUSC 模拟赛 day2 下午总结

    终于考完了,下午身体状况很不好,看来要锻炼身体了,不然以后ACM没准比赛到一半我就挂掉了 下午差点AK,有一道很简单的题我看错题面了所以没有A掉 第一题显然是非常丝薄的题目 我们很容易通过DP来O(n ...