/**************************************************************//**
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. linux 学习笔记2

    vi  编辑命令并查看 i 插入 esc  转换模式 shift + : x  保存并退出    q  不保存  !强制保存 五个查看命令 cat / less / more / tail / hea ...

  2. MySql 服务端与客户端下载地址

    mysql官网的注册,要上传户口,才能下载. 在网上搜了个下载地址. mysql-5.6.8-rc http://mysql.stu.edu.tw/Downloads/MySQL-5.6/mysql- ...

  3. try、catch、finally的使用分析---与 return 相关

    看了一篇文章,讲解的是关于java中关于try.catch.finally中一些问题 下面看一个例子(例1),来讲解java里面中try.catch.finally的处理流程   1 2 3 4 5 ...

  4. Python遍历路径下所有文件

    开始学Python,这篇文章来自于应用需求. os.walk很方便,下面写了两个版本的函数进行遍历,分别是不使用walk和使用walk的. import sys import string impor ...

  5. Python调用C模块以及性能分析

    一.c,ctypes和python的数据类型的对应关系 ctypes type ctype Python type c_char char 1-character string c_wchar wch ...

  6. .NET中的弱引用

    弱引用是什么? 要搞清楚什么是弱引用,我们需要先知道强引用是什么.强引用并不是什么深奥的概念,其实我们平时所使用的.Net引用就是强引用.例如: Cat cat = new Cat(); 变量cat就 ...

  7. Android Studio 单刷《第一行代码》系列目录

    前言(Prologue) 本系列将使用 Android Studio 将<第一行代码>(书中讲解案例使用Eclipse)刷一遍,旨在为想入坑 Android 开发,并选择 Android ...

  8. office2010 office2013打开个别PPT时需要修复的解决方法

    写在前面的废话(请直接查看正文部分):一次意外之后,需要重装Microsoft office,于是屁颠屁颠就重装了一次MS office 2013,装好后发现,打开个别ppt/pptx时打不开,提示修 ...

  9. CROSS APPLY vs OUTER APPLY

    Apply 工作原理:    Apply操作符让符合查询的每一条记录都调用一次TVF函数,并将结果与原数据表的记录内容一起展开.    Apply操作符定义在From子句内,使用方式与Join操作符类 ...

  10. BZOJ 4146 [AMPPZ2014] Divisors 解题报告

    这个题感觉比较小清新... 我们记录每个数出现的次数 $T_i$. 首先依次枚举每个数字,令 $ans = ans + T_i \times (T_i - 1)$,然后枚举这个数的倍数,令 $ans ...