/********************************************************************//**
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的更多相关文章

  1. Python 小而美的函数

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

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

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

  3. JavaScript权威指南 - 函数

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

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

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

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

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

  6. javascript中的this与函数讲解

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

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

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

  8. JS核心系列:浅谈函数的作用域

    一.作用域(scope) 所谓作用域就是:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的. function scope(){ var foo = "global&quo ...

  9. C++中的时间函数

    C++获取时间函数众多,何时该用什么函数,拿到的是什么时间?该怎么用?很多人都会混淆. 本文是本人经历了几款游戏客户端和服务器开发后,对游戏中时间获取的一点总结. 最早学习游戏客户端时,为了获取最精确 ...

随机推荐

  1. c语言编程之队列(链表实现)

    用链表实现了队列,完成了队列的入队和出队功能. #include"stdio.h" typedef int element; typedef struct Node{ struct ...

  2. c# 取 list前100条数据

    [问] List<KeyWord> sortedList = (from a in keyWordList orderby a.Total descending select a).ToL ...

  3. vi 常用技巧

    vi/vim : Visual Interface/VI iMproved VI命令可以说是Unix/Linux世界里最常用的编辑文件的命令了,但是因为它的命令集众多,很多人都不习惯使用它,其实您只需 ...

  4. mysql merge

    merge 是一组 myisam 表的组合, 锁住一个 merge 表它会吧底下所有的表全给锁住. 创建只读表 )) engine = merge union (t1,t2); 创建可插入的表, (以 ...

  5. 混乱的url编码||URL编码解码问题

    转载自:http://www.ruanyifeng.com/blog/2010/02/url_encoding.html 一.问题的由来. url就是网址,只要上网就一定会用到. 一般来说,URL只能 ...

  6. AlphaToCoverage solution

    After msaa output the alpha in ps remove clip in ps in blendstate add AlphaToCoverageEnable = TRUE - ...

  7. Codeforces Round #256 (Div. 2) Multiplication Table

    C题, #include<cstdio> #include<cstring> #include<algorithm> #define maxn 5005 using ...

  8. NGUI UIGrid 动态刷新布局 && BUG FIX

    /// <summary> /// "1" => 对应的一个UISpirte,"1234" => 对应四个预设 /// </sum ...

  9. log4j使用感受

    1.为什么使用日志? 日志可以记录项目中的重要信息,关键输出信息,异常信息,为项目上线后期维护提供方便,在项目开发中尽量养成习惯写日志,而不是System.out.println()打印,不过在jun ...

  10. 对于python的内存管理的好文章

    http://www.cnblogs.com/vamei/p/3232088.html 包含了一个绘制关系图的包