/**************************************************************//**
NOTE! The following macros should be used instead of buf_page_get_gen,
to improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed
in LA! */
#define buf_page_get(SP, ZS, OF, LA, MTR)     buf_page_get_gen(\
                SP, ZS, OF, LA, NULL,\
                BUF_GET, __FILE__, __LINE__, MTR)

/********************************************************************//**
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));
#ifdef UNIV_DEBUG
    switch (mode) {
    case BUF_GET_NO_LATCH:
        ut_ad(rw_latch == RW_NO_LATCH);
        break;
    case BUF_GET:
    case BUF_GET_IF_IN_POOL:
    case BUF_PEEK_IF_IN_POOL:
    case BUF_GET_IF_IN_POOL_OR_WATCH:
    case BUF_GET_POSSIBLY_FREED:
        break;
    default:
        ut_error;
    }
#endif /* UNIV_DEBUG */
    ut_ad(zip_size == fil_space_get_zip_size(space));
    ut_ad(ut_is_2pow(zip_size));
#ifndef UNIV_LOG_DEBUG
    ut_ad(!ibuf_inside(mtr)
          || ibuf_page_low(space, zip_size, offset,
                   FALSE, file, line, NULL));
#endif
    buf_pool->stat.n_page_gets++;
    fold = buf_page_address_fold(space, offset);
loop:
    block = guess;
    buf_pool_mutex_enter(buf_pool);

    if (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) {
        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 */

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

  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. JavaScript 高级程序设计 目录

    为什么会写这个学习教程呢??因为一直以来,学习JavaScript都没有系统的学过,用什么学什么,所以今天开始,重新把JavaScript系统的学一遍!(本人也是菜鸟一枚,语文水平也还是小学程度,看得 ...

  2. 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句

    这次给大家介绍一下在Java开发过程中 使用自定义注解开发:主要知识点:            1.反射            主要用于提取注解信息            2.自定义异常  主要是为了 ...

  3. Sybase 导入导出命令

    BCP命令详解 BCP是SYBASE公司提供专门用于数据库表一级数据备份的工具. 一般存放在所安装的ASE或者Open Client 的BIN目录中. 可执行文件名称为bcp.EXE 参数列表如下:( ...

  4. HDU 3487 Splay

    给定两种操作,一种是把一个数列的某一段切下来插到剩余数列的某一个位置上. 一种是翻转操作,把数列的某一段进行翻转. 都是Splay的基本操作.标准的Rotateto调整出 [a,b]区间.然后对[a, ...

  5. parsing html in asp.net

    http://stackoverflow.com/questions/5307374/parsing-html-page-in-asp-net http://htmlagilitypack.codep ...

  6. EF当实体模型与数据库的架构不同时要删除数据库时的报错问题

    当使用的EF的时候,我们都知道EF当实体模型与数据库的架构不同时要删除数据库,这是会把错: 无法创建与 'master' 数据库之间的连接,这是因为已打开原始数据库连接,并且已从连接字符串中删除凭据. ...

  7. C#中用ILMerge将所有引用的DLL打成一个DLL文件

    有些文件是必须一起使用的,如果能把多个DLL打包成一个DLL文件,那么引用文件的时候就不需要一个个地去引用,而且每次移动文件的时候也不至于少了哪个必须的DLL文件. 多个DLL文件打包成一个DLL文件 ...

  8. vs中使用过的扩展和好的nuget库

    扩展 ReAttach ReAttach gives you an easy way to ReAttaching your prior debug targets. ReAttach stores ...

  9. Hibernate应用SQL查询返回实体类型

    Hibernate应用SQL查询返回实体类型 Hibernate使用SQL查询返回实体类型 以前,使用SQL查询,结果放在 RS 结果集中,还要去转换影射到Java类中.Hibernate中,可以自动 ...

  10. 团体程序设计天梯赛-练习集L2-006. 树的遍历

    L2-006. 树的遍历 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历 ...