innodb buffer pool中的page hash表

660阅读 0评论2013-02-19 gladness
分类:Mysql/postgreSQL

这是mysql5.5.28的版本


/******************************************************************//**

Returns the control block of a file page, NULL if not found.

@return  block, NULL if not found */

UNIV_INLINE

buf_page_t*

buf_page_hash_get_low(

/*==================*/

     buf_pool_t*   buf_pool, /*!< buffer pool instance */

     ulint         space,        /*!< in: space id */

     ulint         offset,       /*!< in: offset of the page

                       within space */

     ulint         fold)         /*!< in: buf_page_address_fold(

                       space, offset) */

{

     buf_page_t*   bpage;

 

     ut_ad(buf_pool);

     ut_ad(buf_pool_mutex_own(buf_pool));

     ut_ad(fold == buf_page_address_fold(space, offset));

 

     /* Look for the page in the hash table */

 

     HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,

             ut_ad(bpage->in_page_hash && !bpage->in_zip_hash

                && buf_page_in_file(bpage)),

             bpage->space == space && bpage->offset == offset);

     if (bpage) {

         ut_a(buf_page_in_file(bpage));

         ut_ad(bpage->in_page_hash);

         ut_ad(!bpage->in_zip_hash);

#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(bpage, sizeof *bpage);

#endif

     }

 

     return(bpage);

}

 

 

/*******************************************************************//**

Gets the first struct in a hash chain, NULL if none. */

 

#define HASH_GET_FIRST(TABLE, HASH_VAL)\

     (hash_get_nth_cell(TABLE, HASH_VAL)->node)

 

/*******************************************************************//**

Gets the next struct in a hash chain, NULL if none. */

 

#define HASH_GET_NEXT(NAME, DATA)    ((DATA)->NAME)

 

/********************************************************************//**

Looks for a struct in a hash table. */

#define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\

{\

\

     HASH_ASSERT_OWNED(TABLE, FOLD)\

\

     (DATA) = (TYPE) HASH_GET_FIRST(TABLE, hash_calc_hash(FOLD, TABLE));\

     HASH_ASSERT_VALID(DATA);\

\

     while ((DATA) != NULL) {\

         ASSERTION;\

         if (TEST) {\

              break;\

         } else {\

              HASH_ASSERT_VALID(HASH_GET_NEXT(NAME, DATA));\

              (DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA);\

         }\

     }\

}

 

 

替换宏

{\

\

     HASH_ASSERT_OWNED(buf_pool->page_hash, fold)\

\

/*hash_calc_hash计算出HASH值;

HASH_GET_FIRST利用buf_pool->page_hash这个HASH表以及hash_calc_hash返回的值,不妨称为n

调用hash_get_nth_cell,得到HASH表(是一个数组)中第n个对象,类型是hash_cell_t*

获取其所指对象的node属性*/

     (bpage) = (buf_page_t*) HASH_GET_FIRST(buf_pool->page_hash, hash_calc_hash(fold, buf_pool->page_hash));\

     HASH_ASSERT_VALID(bpage);\

\

     while ((bpage) != NULL) {\

         ASSERTION;\

         /*HASH值相等的对象可能有多个,在同一个链表里,因此还要核对一下该对象的spaceoffset*/

         if (bpage->space == space && bpage->offset == offset) {\

              break;\

         } else {\

              HASH_ASSERT_VALID(HASH_GET_NEXT(hash, bpage));\

              (bpage) = (buf_page_t*)(bpage->hash);/*这是一个链表,同一个HASH值的对象,放在同一个链表里*/

         }\

     }\

}

 

 

 

/**************************************************************//**

Calculates the hash value from a folded value.

@return hashed value */

UNIV_INLINE

ulint

hash_calc_hash(

/*===========*/

    ulint       fold,   /*!< in: folded value */

    hash_table_t*   table)  /*!< in: hash table */

{

    ut_ad(table);

    ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);

    return(ut_hash_ulint(fold, table->n_cells));

}

 

/*******************************************************//**

The following function generates a hash value for a ulint integer

to a hash table of size table_size, which should be a prime

or some random number for the hash table to work reliably.

@return hash value */

UNIV_INLINE

ulint

ut_hash_ulint(

/*==========*/

    ulint    key,       /*!< in: value to be hashed */

    ulint    table_size)    /*!< in: hash table size */

{

    ut_ad(table_size);

    key = key ^ UT_HASH_RANDOM_MASK2;

 

    return(key % table_size);

}

 

#define UT_HASH_RANDOM_MASK2    1653893711

 

/************************************************************//**

Gets the nth cell in a hash table.

@return  pointer to cell */

UNIV_INLINE

hash_cell_t*

hash_get_nth_cell(

/*==============*/

     hash_table_t* table,   /*!< in: hash table */

     ulint         n)   /*!< in: cell index */

{

     ut_ad(table);

     ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);

     ut_ad(n < table->n_cells);

 

     return(table->array + n);

}

 

typedef struct hash_cell_struct hash_cell_t;

 

struct hash_cell_struct{

    void*   node;   /*!< hash chain node, NULL if none */

};

 

typedef    struct buf_page_struct          buf_page_t;

 

struct buf_page_struct{

    /** @name General fields

    None of these bit-fields must be modified without holding

    buf_page_get_mutex() [buf_block_struct::mutex or

    buf_pool->zip_mutex], since they can be stored in the same

    machine word.  Some of these fields are additionally protected

    by buf_pool->mutex. */

    /* @{ */

 

    unsigned    space:32;   /*!< tablespace id; also protected

                    by buf_pool->mutex. */

    unsigned    offset:32;  /*!< page number; also protected

                    by buf_pool->mutex. */

 

    unsigned    state:BUF_PAGE_STATE_BITS;

                    /*!< state of the control block; also

                    protected by buf_pool->mutex.

                    State transitions from

                    BUF_BLOCK_READY_FOR_USE to

                    BUF_BLOCK_MEMORY need not be

                    protected by buf_page_get_mutex().

                    @see enum buf_page_state */

#ifndef UNIV_HOTBACKUP

    unsigned    flush_type:2;   /*!< if this block is currently being

                    flushed to disk, this tells the

                    flush_type.

                    @see enum buf_flush */

    unsigned    io_fix:2;   /*!< type of pending I/O operation;

                    also protected by buf_pool->mutex

                    @see enum buf_io_fix */

    unsigned    buf_fix_count:19;/*!< count of how manyfold this block

                    is currently bufferfixed */

    unsigned    buf_pool_index:6;/*!< index number of the buffer pool

                    that this block belongs to */

# if MAX_BUFFER_POOLS > 64

#  error "MAX_BUFFER_POOLS > 64; redefine buf_pool_index:6"

# endif

    /* @} */

#endif /* !UNIV_HOTBACKUP */

    page_zip_des_t  zip;        /*!< compressed page; zip.data

                    (but not the data it points to) is

                    also protected by buf_pool->mutex;

                    state == BUF_BLOCK_ZIP_PAGE and

                    zip.data == NULL means an active

                    buf_pool->watch */

#ifndef UNIV_HOTBACKUP

    buf_page_t* hash;       /*!< node used in chaining to

                    buf_pool->page_hash or

                    buf_pool->zip_hash */

#ifdef UNIV_DEBUG

    ibool       in_page_hash;   /*!< TRUE if in buf_pool->page_hash */

    ibool       in_zip_hash;    /*!< TRUE if in buf_pool->zip_hash */

#endif /* UNIV_DEBUG */

    /** @name Page flushing fields

    All these are protected by buf_pool->mutex. */

    /* @{ */

 

    /* UT_LIST_NODE_T(buf_page_t) list; */

                    /*!< based on state, this is a

                    list node, protected either by

                    buf_pool->mutex or by

                    buf_pool->flush_list_mutex,

                    in one of the following lists in

                    buf_pool:

 

                    - BUF_BLOCK_NOT_USED:   free

                    - BUF_BLOCK_FILE_PAGE:  flush_list

                    - BUF_BLOCK_ZIP_DIRTY:  flush_list

                    - BUF_BLOCK_ZIP_PAGE:   zip_clean

                    - BUF_BLOCK_ZIP_FREE:   zip_free[]

 

                    If bpage is part of flush_list

                    then the node pointers are

                    covered by buf_pool->flush_list_mutex.

                    Otherwise these pointers are

                    protected by buf_pool->mutex.

 

                    The contents of the list node

                    is undefined if !in_flush_list

                    && state == BUF_BLOCK_FILE_PAGE,

                    or if state is one of

                    BUF_BLOCK_MEMORY,

                    BUF_BLOCK_REMOVE_HASH or

                    BUF_BLOCK_READY_IN_USE. */

 

    /* resplit for optimistic use */

    UT_LIST_NODE_T(buf_page_t) free;

    UT_LIST_NODE_T(buf_page_t) flush_list;

    UT_LIST_NODE_T(buf_page_t) zip_list; /* zip_clean or zip_free[] */

#ifdef UNIV_DEBUG

    ibool       in_flush_list;  /*!< TRUE if in buf_pool->flush_list;

                    when buf_pool->flush_list_mutex is

                    free, the following should hold:

                    in_flush_list

                    == (state == BUF_BLOCK_FILE_PAGE

                        || state == BUF_BLOCK_ZIP_DIRTY)

                    Writes to this field must be

                    covered by both block->mutex

                    and buf_pool->flush_list_mutex. Hence

                    reads can happen while holding

                    any one of the two mutexes */

    ibool       in_free_list;   /*!< TRUE if in buf_pool->free; when

                    buf_pool->mutex is free, the following

                    should hold: in_free_list

                    == (state == BUF_BLOCK_NOT_USED) */

#endif /* UNIV_DEBUG */

    ib_uint64_t newest_modification;

                    /*!< log sequence number of

                    the youngest modification to

                    this block, zero if not

                    modified. Protected by block

                    mutex */

    ib_uint64_t oldest_modification;

                    /*!< log sequence number of

                    the START of the log entry

                    written of the oldest

                    modification to this block

                    which has not yet been flushed

                    on disk; zero if all

                    modifications are on disk.

                    Writes to this field must be

                    covered by both block->mutex

                    and buf_pool->flush_list_mutex. Hence

                    reads can happen while holding

                    any one of the two mutexes */

    /* @} */

    /** @name LRU replacement algorithm fields

    These fields are protected by buf_pool->mutex only (not

    buf_pool->zip_mutex or buf_block_struct::mutex). */

    /* @{ */

 

    UT_LIST_NODE_T(buf_page_t) LRU;

                    /*!< node of the LRU list */

//#ifdef UNIV_DEBUG

    ibool       in_LRU_list;    /*!< TRUE if the page is in

                    the LRU list; used in

                    debugging */

//#endif /* UNIV_DEBUG */

    unsigned    old:1;      /*!< TRUE if the block is in the old

                    blocks in buf_pool->LRU_old */

    unsigned    freed_page_clock:31;/*!< the value of

                    buf_pool->freed_page_clock

                    when this block was the last

                    time put to the head of the

                    LRU list; a thread is allowed

                    to read this for heuristic

                    purposes without holding any

                    mutex or latch */

    unsigned    access_time:32; /*!< time of first access, or

                    0 if the block was never accessed

                    in the buffer pool */

    /* @} */

    ibool       space_was_being_deleted;

    ibool       is_corrupt;

# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG

    ibool       file_page_was_freed;

                    /*!< this is set to TRUE when fsp

                    frees a page in buffer pool */

# endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */

#endif /* !UNIV_HOTBACKUP */

};

 

 

 

/*************************************************************//**

Creates a hash table with >= n array cells. The actual number of cells is

chosen to be a prime number slightly bigger than n.

@return  own: created table */

UNIV_INTERN

hash_table_t*

hash_create(

/*========*/

     ulint    n)   /*!< in: number of array cells */

{

     hash_cell_t*  array;

     ulint         prime;

     hash_table_t* table;

 

     prime = ut_find_prime(n);

 

     table = mem_alloc(sizeof(hash_table_t));

 

     array = ut_malloc(sizeof(hash_cell_t) * prime);

 

     table->array = array;

     table->n_cells = prime;

#ifndef UNIV_HOTBACKUP

# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG

     table->adaptive = FALSE;

# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */

     table->n_mutexes = 0;

     table->mutexes = NULL;

     table->heaps = NULL;

#endif /* !UNIV_HOTBACKUP */

     table->heap = NULL;

     ut_d(table->magic_n = HASH_TABLE_MAGIC_N);

 

     /* Initialize the cell array */

     hash_table_clear(table);

 

     return(table);

}


上一篇:row_ins_index_entry_low函数的注释
下一篇:innodb buffer pool初始化