diff options
author | Igor Babaev <igor@askmonty.org> | 2012-12-16 16:49:19 -0800 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2012-12-16 16:49:19 -0800 |
commit | 7760efad74140680b1eefaf2172b0fa26f7b1146 (patch) | |
tree | 57742baa180206a1cd3ea35d38c58108accd22a9 /storage/innobase | |
parent | 40bbf697aad7d923fc1bd995bc5f547e45461cbe (diff) | |
parent | b8b875cb796743240bed71857eae73d37f03c28f (diff) | |
download | mariadb-git-7760efad74140680b1eefaf2172b0fa26f7b1146.tar.gz |
Merge mariadb-5.5 -> 10.0-base.
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/btr/btr0btr.c | 47 | ||||
-rw-r--r-- | storage/innobase/btr/btr0cur.c | 39 | ||||
-rw-r--r-- | storage/innobase/btr/btr0pcur.c | 67 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.c | 11 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 5 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.cc | 1853 | ||||
-rw-r--r-- | storage/innobase/handler/i_s.h | 3 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.c | 17 | ||||
-rw-r--r-- | storage/innobase/include/buf0buf.h | 33 | ||||
-rw-r--r-- | storage/innobase/include/buf0buf.ic | 26 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 2 | ||||
-rw-r--r-- | storage/innobase/include/log0log.h | 3 | ||||
-rw-r--r-- | storage/innobase/page/page0cur.c | 1 | ||||
-rw-r--r-- | storage/innobase/page/page0page.c | 31 | ||||
-rw-r--r-- | storage/innobase/row/row0ins.c | 9 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.c | 14 |
16 files changed, 2072 insertions, 89 deletions
diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index b714219e304..a6fdff72f50 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -1844,6 +1844,7 @@ btr_root_raise_and_insert( root = btr_cur_get_page(cursor); root_block = btr_cur_get_block(cursor); root_page_zip = buf_block_get_page_zip(root_block); + ut_ad(page_get_n_recs(root) > 0); #ifdef UNIV_ZIP_DEBUG ut_a(!root_page_zip || page_zip_validate(root_page_zip, root)); #endif /* UNIV_ZIP_DEBUG */ @@ -2324,12 +2325,20 @@ btr_insert_on_non_leaf_level_func( BTR_CONT_MODIFY_TREE, &cursor, 0, file, line, mtr); - err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG - | BTR_KEEP_SYS_FLAG - | BTR_NO_UNDO_LOG_FLAG, - &cursor, tuple, &rec, - &dummy_big_rec, 0, NULL, mtr); - ut_a(err == DB_SUCCESS); + ut_ad(cursor.flag == BTR_CUR_BINARY); + + err = btr_cur_optimistic_insert( + BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG + | BTR_NO_UNDO_LOG_FLAG, &cursor, tuple, &rec, + &dummy_big_rec, 0, NULL, mtr); + + if (err == DB_FAIL) { + err = btr_cur_pessimistic_insert( + BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG + | BTR_NO_UNDO_LOG_FLAG, + &cursor, tuple, &rec, &dummy_big_rec, 0, NULL, mtr); + ut_a(err == DB_SUCCESS); + } } /**************************************************************//** @@ -3254,6 +3263,7 @@ btr_compress( if (adjust) { nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor)); + ut_ad(nth_rec > 0); } /* Decide the page to which we try to merge and which will inherit @@ -3489,6 +3499,7 @@ func_exit: mem_heap_free(heap); if (adjust) { + ut_ad(nth_rec > 0); btr_cur_position( index, page_rec_get_nth(merge_block->frame, nth_rec), @@ -4002,8 +4013,22 @@ btr_index_page_validate( { page_cur_t cur; ibool ret = TRUE; +#ifndef DBUG_OFF + ulint nth = 1; +#endif /* !DBUG_OFF */ page_cur_set_before_first(block, &cur); + + /* Directory slot 0 should only contain the infimum record. */ + DBUG_EXECUTE_IF("check_table_rec_next", + ut_a(page_rec_get_nth_const( + page_cur_get_page(&cur), 0) + == cur.rec); + ut_a(page_dir_slot_get_n_owned( + page_dir_get_nth_slot( + page_cur_get_page(&cur), 0)) + == 1);); + page_cur_move_to_next(&cur); for (;;) { @@ -4017,6 +4042,16 @@ btr_index_page_validate( return(FALSE); } + /* Verify that page_rec_get_nth_const() is correctly + retrieving each record. */ + DBUG_EXECUTE_IF("check_table_rec_next", + ut_a(cur.rec == page_rec_get_nth_const( + page_cur_get_page(&cur), + page_rec_get_n_recs_before( + cur.rec))); + ut_a(nth++ == page_rec_get_n_recs_before( + cur.rec));); + page_cur_move_to_next(&cur); } diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index 9c61e0cf763..ce43cba8525 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -1323,7 +1323,12 @@ fail_err: if (UNIV_UNLIKELY(reorg)) { ut_a(zip_size); - ut_a(*rec); + /* It's possible for rec to be NULL if the + page is compressed. This is because a + reorganized page may become incompressible. */ + if (!*rec) { + goto fail; + } } } @@ -1459,20 +1464,9 @@ btr_cur_pessimistic_insert( ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor), MTR_MEMO_PAGE_X_FIX)); - /* Try first an optimistic insert; reset the cursor flag: we do not - assume anything of how it was positioned */ - cursor->flag = BTR_CUR_BINARY; - err = btr_cur_optimistic_insert(flags, cursor, entry, rec, - big_rec, n_ext, thr, mtr); - if (err != DB_FAIL) { - - return(err); - } - - /* Retry with a pessimistic insert. Check locks and write to undo log, - if specified */ + /* Check locks and write to undo log, if specified */ err = btr_cur_ins_lock_and_undo(flags, cursor, entry, thr, mtr, &dummy_inh); @@ -2076,8 +2070,12 @@ any_extern: goto err_exit; } - max_size = old_rec_size - + page_get_max_insert_size_after_reorganize(page, 1); + /* We do not attempt to reorganize if the page is compressed. + This is because the page may fail to compress after reorganization. */ + max_size = page_zip + ? page_get_max_insert_size(page, 1) + : (old_rec_size + + page_get_max_insert_size_after_reorganize(page, 1)); if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT) && (max_size >= new_rec_size)) @@ -2433,7 +2431,12 @@ make_external: err = DB_SUCCESS; goto return_after_reservations; } else { - ut_a(optim_err != DB_UNDERFLOW); + /* If the page is compressed and it initially + compresses very well, and there is a subsequent insert + of a badly-compressing record, it is possible for + btr_cur_optimistic_update() to return DB_UNDERFLOW and + btr_cur_insert_if_possible() to return FALSE. */ + ut_a(page_zip || optim_err != DB_UNDERFLOW); /* Out of space: reset the free bits. */ if (!dict_index_is_clust(index) @@ -2462,7 +2465,9 @@ make_external: was_first = page_cur_is_before_first(page_cursor); /* Lock checks and undo logging were already performed by - btr_cur_upd_lock_and_undo(). */ + btr_cur_upd_lock_and_undo(). We do not try + btr_cur_optimistic_insert() because + btr_cur_insert_if_possible() already failed above. */ err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG | BTR_NO_LOCKING_FLAG diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 7ac96c1a1b1..c989498408a 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -348,44 +348,39 @@ btr_pcur_restore_position_func( /* Restore the old search mode */ cursor->search_mode = old_mode; - if (btr_pcur_is_on_user_rec(cursor)) { - switch (cursor->rel_pos) { - case BTR_PCUR_ON: - if (!cmp_dtuple_rec( - tuple, btr_pcur_get_rec(cursor), - rec_get_offsets(btr_pcur_get_rec(cursor), - index, NULL, - ULINT_UNDEFINED, &heap))) { - - /* We have to store the NEW value for - the modify clock, since the cursor can - now be on a different page! But we can - retain the value of old_rec */ - - cursor->block_when_stored = - btr_pcur_get_block(cursor); - cursor->modify_clock = - buf_block_get_modify_clock( - cursor->block_when_stored); - cursor->old_stored = BTR_PCUR_OLD_STORED; - - mem_heap_free(heap); - - return(TRUE); - } - - break; - case BTR_PCUR_BEFORE: - page_cur_move_to_next(btr_pcur_get_page_cur(cursor)); - break; - case BTR_PCUR_AFTER: - page_cur_move_to_prev(btr_pcur_get_page_cur(cursor)); - break; + switch (cursor->rel_pos) { + case BTR_PCUR_ON: + if (btr_pcur_is_on_user_rec(cursor) + && !cmp_dtuple_rec( + tuple, btr_pcur_get_rec(cursor), + rec_get_offsets(btr_pcur_get_rec(cursor), + index, NULL, + ULINT_UNDEFINED, &heap))) { + + /* We have to store the NEW value for + the modify clock, since the cursor can + now be on a different page! But we can + retain the value of old_rec */ + + cursor->block_when_stored = + btr_pcur_get_block(cursor); + cursor->modify_clock = + buf_block_get_modify_clock( + cursor->block_when_stored); + cursor->old_stored = BTR_PCUR_OLD_STORED; + + mem_heap_free(heap); + + return(TRUE); + } #ifdef UNIV_DEBUG - default: - ut_error; + /* fall through */ + case BTR_PCUR_BEFORE: + case BTR_PCUR_AFTER: + break; + default: + ut_error; #endif /* UNIV_DEBUG */ - } } mem_heap_free(heap); diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 32d376136e6..70841a168ab 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -294,14 +294,7 @@ be effective only if PFS_GROUP_BUFFER_SYNC is defined. */ # endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */ #endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */ -/** A chunk of buffers. The buffer pool is allocated in chunks. */ -struct buf_chunk_struct{ - ulint mem_size; /*!< allocated size of the chunk */ - ulint size; /*!< size of frames[] and blocks[] */ - void* mem; /*!< pointer to the memory area which - was allocated for the frames */ - buf_block_t* blocks; /*!< array of buffer control blocks */ -}; + /********************************************************************//** Gets the smallest oldest_modification lsn for any page in the pool. Returns @@ -4424,7 +4417,7 @@ buf_stats_aggregate_pool_info( Collect buffer pool stats information for a buffer pool. Also record aggregated stats if there are more than one buffer pool in the server */ -static +UNIV_INTERN void buf_stats_get_pool_info( /*====================*/ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f8450cb89f0..42b0fe2b65f 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -11986,7 +11986,10 @@ i_s_innodb_lock_waits, i_s_innodb_cmp, i_s_innodb_cmp_reset, i_s_innodb_cmpmem, -i_s_innodb_cmpmem_reset +i_s_innodb_cmpmem_reset, +i_s_innodb_buffer_page, +i_s_innodb_buffer_page_lru, +i_s_innodb_buffer_stats mysql_declare_plugin_end; /** @brief Initialize the default value of innodb_commit_concurrency. diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index abbb8b10ce7..59ea065c5c7 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -45,8 +45,93 @@ extern "C" { #include "srv0start.h" /* for srv_was_started */ #include "trx0i_s.h" #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */ +#include "btr0btr.h" +#include "page0zip.h" +#include "log0log.h" } +/** structure associates a name string with a file page type and/or buffer +page state. */ +struct buffer_page_desc_str_struct{ + const char* type_str; /*!< String explain the page + type/state */ + ulint type_value; /*!< Page type or page state */ +}; + +typedef struct buffer_page_desc_str_struct buf_page_desc_str_t; + +/** Any states greater than FIL_PAGE_TYPE_LAST would be treated as unknown. */ +#define I_S_PAGE_TYPE_UNKNOWN (FIL_PAGE_TYPE_LAST + 1) + +/** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position +in i_s_page_type[] array */ +#define I_S_PAGE_TYPE_INDEX 1 + +/** Name string for File Page Types */ +static buf_page_desc_str_t i_s_page_type[] = { + {"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED}, + {"INDEX", FIL_PAGE_INDEX}, + {"UNDO_LOG", FIL_PAGE_UNDO_LOG}, + {"INODE", FIL_PAGE_INODE}, + {"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST}, + {"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP}, + {"SYSTEM", FIL_PAGE_TYPE_SYS}, + {"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS}, + {"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR}, + {"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES}, + {"BLOB", FIL_PAGE_TYPE_BLOB}, + {"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB}, + {"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2}, + {"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN} +}; + +/* Check if we can hold all page type in a 4 bit value */ +#if I_S_PAGE_TYPE_UNKNOWN > 1<<4 +# error "i_s_page_type[] is too large" +#endif + +/** This structure defines information we will fetch from pages +currently cached in the buffer pool. It will be used to populate +table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */ +struct buffer_page_info_struct{ + ulint block_id; /*!< Buffer Pool block ID */ + unsigned space_id:32; /*!< Tablespace ID */ + unsigned page_num:32; /*!< Page number/offset */ + unsigned access_time:32; /*!< Time of first access */ + unsigned pool_id:MAX_BUFFER_POOLS_BITS; + /*!< Buffer Pool ID. Must be less than + MAX_BUFFER_POOLS */ + unsigned flush_type:2; /*!< Flush type */ + unsigned io_fix:2; /*!< type of pending I/O operation */ + unsigned fix_count:19; /*!< Count of how manyfold this block + is bufferfixed */ + unsigned hashed:1; /*!< Whether hash index has been + built on this page */ + unsigned is_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 */ + unsigned zip_ssize:PAGE_ZIP_SSIZE_BITS; + /*!< Compressed page size */ + unsigned page_state:BUF_PAGE_STATE_BITS; /*!< Page state */ + unsigned page_type:4; /*!< Page type */ + unsigned num_recs:UNIV_PAGE_SIZE_SHIFT-2; + /*!< Number of records on Page */ + unsigned data_size:UNIV_PAGE_SIZE_SHIFT; + /*!< Sum of the sizes of the records */ + lsn_t newest_mod; /*!< Log sequence number of + the youngest modification */ + lsn_t oldest_mod; /*!< Log sequence number of + the oldest modification */ + index_id_t index_id; /*!< Index ID if a index page */ +}; + +typedef struct buffer_page_info_struct buf_page_info_t; + +/** maximum number of buffer page info we would cache. */ +#define MAX_BUF_INFO_CACHED 10000 + + #define OK(expr) \ if ((expr) != 0) { \ DBUG_RETURN(1); \ @@ -1792,6 +1877,1772 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset = STRUCT_FLD(flags, 0UL), }; +/* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */ +static ST_FIELD_INFO i_s_innodb_buffer_stats_fields_info[] = +{ +#define IDX_BUF_STATS_POOL_ID 0 + {STRUCT_FLD(field_name, "POOL_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_POOL_SIZE 1 + {STRUCT_FLD(field_name, "POOL_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FREE_BUFFERS 2 + {STRUCT_FLD(field_name, "FREE_BUFFERS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_LEN 3 + {STRUCT_FLD(field_name, "DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_OLD_LRU_LEN 4 + {STRUCT_FLD(field_name, "OLD_DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LIST_LEN 5 + {STRUCT_FLD(field_name, "MODIFIED_DATABASE_PAGES"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PENDING_ZIP 6 + {STRUCT_FLD(field_name, "PENDING_DECOMPRESS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PENDING_READ 7 + {STRUCT_FLD(field_name, "PENDING_READS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LRU 8 + {STRUCT_FLD(field_name, "PENDING_FLUSH_LRU"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_FLUSH_LIST 9 + {STRUCT_FLD(field_name, "PENDING_FLUSH_LIST"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_YOUNG 10 + {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_NOT_YOUNG 11 + {STRUCT_FLD(field_name, "PAGES_NOT_MADE_YOUNG"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_YOUNG_RATE 12 + {STRUCT_FLD(field_name, "PAGES_MADE_YOUNG_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13 + {STRUCT_FLD(field_name, "PAGES_MADE_NOT_YOUNG_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_READ 14 + {STRUCT_FLD(field_name, "NUMBER_PAGES_READ"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_CREATED 15 + {STRUCT_FLD(field_name, "NUMBER_PAGES_CREATED"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_WRITTEN 16 + {STRUCT_FLD(field_name, "NUMBER_PAGES_WRITTEN"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_READ_RATE 17 + {STRUCT_FLD(field_name, "PAGES_READ_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_CREATE_RATE 18 + {STRUCT_FLD(field_name, "PAGES_CREATE_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_PAGE_WRITTEN_RATE 19 + {STRUCT_FLD(field_name, "PAGES_WRITTEN_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_GET 20 + {STRUCT_FLD(field_name, "NUMBER_PAGES_GET"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_HIT_RATE 21 + {STRUCT_FLD(field_name, "HIT_RATE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_MADE_YOUNG_PCT 22 + {STRUCT_FLD(field_name, "YOUNG_MAKE_PER_THOUSAND_GETS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23 + {STRUCT_FLD(field_name, "NOT_YOUNG_MAKE_PER_THOUSAND_GETS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHREAD 24 + {STRUCT_FLD(field_name, "NUMBER_PAGES_READ_AHEAD"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_EVICTED 25 + {STRUCT_FLD(field_name, "NUMBER_READ_AHEAD_EVICTED"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_RATE 26 + {STRUCT_FLD(field_name, "READ_AHEAD_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27 + {STRUCT_FLD(field_name, "READ_AHEAD_EVICTED_RATE"), + STRUCT_FLD(field_length, MAX_FLOAT_STR_LENGTH), + STRUCT_FLD(field_type, MYSQL_TYPE_FLOAT), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, 0), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_IO_SUM 28 + {STRUCT_FLD(field_name, "LRU_IO_TOTAL"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_LRU_IO_CUR 29 + {STRUCT_FLD(field_name, "LRU_IO_CURRENT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_UNZIP_SUM 30 + {STRUCT_FLD(field_name, "UNCOMPRESS_TOTAL"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_STATS_UNZIP_CUR 31 + {STRUCT_FLD(field_name, "UNCOMPRESS_CURRENT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular +buffer pool +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_stats_fill( +/*==================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_pool_info_t* info) /*!< in: buffer pool + information */ +{ + TABLE* table; + Field** fields; + + DBUG_ENTER("i_s_innodb_stats_fill"); + + table = tables->table; + + fields = table->field; + + OK(fields[IDX_BUF_STATS_POOL_ID]->store(info->pool_unique_id)); + + OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info->pool_size)); + + OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info->lru_len)); + + OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info->old_lru_len)); + + OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(info->free_list_len)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store( + info->flush_list_len)); + + OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info->n_pend_unzip)); + + OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info->n_pend_reads)); + + OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(info->n_pending_flush_lru)); + + OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(info->n_pending_flush_list)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(info->n_pages_made_young)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store( + info->n_pages_not_made_young)); + + OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store( + info->page_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store( + info->page_not_made_young_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info->n_pages_read)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(info->n_pages_created)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(info->n_pages_written)); + + OK(fields[IDX_BUF_STATS_GET]->store(info->n_page_gets)); + + OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(info->pages_read_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(info->pages_created_rate)); + + OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(info->pages_written_rate)); + + if (info->n_page_get_delta) { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store( + 1000 - (1000 * info->page_read_delta + / info->n_page_get_delta))); + + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store( + 1000 * info->young_making_delta + / info->n_page_get_delta)); + + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store( + 1000 * info->not_young_making_delta + / info->n_page_get_delta)); + } else { + OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0)); + OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0)); + OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0)); + } + + OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(info->n_ra_pages_read)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store( + info->n_ra_pages_evicted)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store( + info->pages_readahead_rate)); + + OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store( + info->pages_evicted_rate)); + + OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info->io_sum)); + + OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info->io_cur)); + + OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info->unzip_sum)); + + OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( info->unzip_cur)); + + DBUG_RETURN(schema_table_store_record(thd, table)); +} + +/*******************************************************************//** +This is the function that loops through each buffer pool and fetch buffer +pool stats to information schema table: I_S_INNODB_BUFFER_POOL_STATS +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_stats_fill_table( +/*===============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + buf_pool_info_t* pool_info; + + DBUG_ENTER("i_s_innodb_buffer_fill_general"); + + /* Only allow the PROCESS privilege holder to access the stats */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + pool_info = (buf_pool_info_t*) mem_zalloc( + srv_buf_pool_instances * sizeof *pool_info); + + /* Walk through each buffer pool */ + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool; + + buf_pool = buf_pool_from_array(i); + + /* Fetch individual buffer pool info */ + buf_stats_get_pool_info(buf_pool, i, pool_info); + + status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]); + + /* If something goes wrong, break and return */ + if (status) { + break; + } + } + + mem_free(pool_info); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_pool_stats_init( +/*==============================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_pool_stats_init"); + + schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p); + + schema->fields_info = i_s_innodb_buffer_stats_fields_info; + schema->fill_table = i_s_innodb_buffer_stats_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_stats = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), +}; + +/* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */ +static ST_FIELD_INFO i_s_innodb_buffer_page_fields_info[] = +{ +#define IDX_BUFFER_POOL_ID 0 + {STRUCT_FLD(field_name, "POOL_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_BLOCK_ID 1 + {STRUCT_FLD(field_name, "BLOCK_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_SPACE 2 + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NUM 3 + {STRUCT_FLD(field_name, "PAGE_NUMBER"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_TYPE 4 + {STRUCT_FLD(field_name, "PAGE_TYPE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FLUSH_TYPE 5 + {STRUCT_FLD(field_name, "FLUSH_TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FIX_COUNT 6 + {STRUCT_FLD(field_name, "FIX_COUNT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_HASHED 7 + {STRUCT_FLD(field_name, "IS_HASHED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NEWEST_MOD 8 + {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_OLDEST_MOD 9 + {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_ACCESS_TIME 10 + {STRUCT_FLD(field_name, "ACCESS_TIME"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_TABLE_NAME 11 + {STRUCT_FLD(field_name, "TABLE_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_INDEX_NAME 12 + {STRUCT_FLD(field_name, "INDEX_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_NUM_RECS 13 + {STRUCT_FLD(field_name, "NUMBER_RECORDS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_DATA_SIZE 14 + {STRUCT_FLD(field_name, "DATA_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_ZIP_SIZE 15 + {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_STATE 16 + {STRUCT_FLD(field_name, "PAGE_STATE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_IO_FIX 17 + {STRUCT_FLD(field_name, "IO_FIX"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_IS_OLD 18 + {STRUCT_FLD(field_name, "IS_OLD"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUFFER_PAGE_FREE_CLOCK 19 + {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_PAGE with information +cached in the buf_page_info_t array +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_fill( +/*========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_page_info_t* info_array, /*!< in: array cached page + info */ + ulint num_page, /*!< in: number of page info + cached */ + mem_heap_t* heap) /*!< in: temp heap memory */ +{ + TABLE* table; + Field** fields; + + DBUG_ENTER("i_s_innodb_buffer_page_fill"); + + table = tables->table; + + fields = table->field; + + /* Iterate through the cached array and fill the I_S table rows */ + for (ulint i = 0; i < num_page; i++) { + const buf_page_info_t* page_info; + const char* table_name; + const char* index_name; + const char* state_str; + enum buf_page_state state; + + page_info = info_array + i; + + table_name = NULL; + index_name = NULL; + state_str = NULL; + + OK(fields[IDX_BUFFER_POOL_ID]->store(page_info->pool_id)); + + OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id)); + + OK(fields[IDX_BUFFER_PAGE_SPACE]->store(page_info->space_id)); + + OK(fields[IDX_BUFFER_PAGE_NUM]->store(page_info->page_num)); + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); + + OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store( + page_info->flush_type)); + + OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store( + page_info->fix_count)); + + if (page_info->hashed) { + OK(field_store_string( + fields[IDX_BUFFER_PAGE_HASHED], "YES")); + } else { + OK(field_store_string( + fields[IDX_BUFFER_PAGE_HASHED], "NO")); + } + + OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store( + (longlong) page_info->newest_mod, true)); + + OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store( + (longlong) page_info->oldest_mod, true)); + + OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store( + page_info->access_time)); + + /* If this is an index page, fetch the index name + and table name */ + if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { + const dict_index_t* index; + + mutex_enter(&dict_sys->mutex); + index = dict_index_get_if_in_cache_low( + page_info->index_id); + + /* Copy the index/table name under mutex. We + do not want to hold the InnoDB mutex while + filling the IS table */ + if (index) { + const char* name_ptr = index->name; + + if (name_ptr[0] == TEMP_INDEX_PREFIX) { + name_ptr++; + } + + index_name = mem_heap_strdup(heap, name_ptr); + + table_name = mem_heap_strdup(heap, + index->table_name); + + } + + mutex_exit(&dict_sys->mutex); + } + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_TABLE_NAME], table_name)); + + OK(field_store_string( + fields[IDX_BUFFER_PAGE_INDEX_NAME], index_name)); + + OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store( + page_info->num_recs)); + + OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store( + page_info->data_size)); + + OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store( + page_info->zip_ssize + ? (PAGE_ZIP_MIN_SIZE >> 1) << page_info->zip_ssize + : 0)); + +#if BUF_PAGE_STATE_BITS > 3 +# error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for" +#endif + state = static_cast<enum buf_page_state>(page_info->page_state); + + switch (state) { + /* First three states are for compression pages and + are not states we would get as we scan pages through + buffer blocks */ + case BUF_BLOCK_ZIP_FREE: + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + state_str = NULL; + break; + case BUF_BLOCK_NOT_USED: + state_str = "NOT_USED"; + break; + case BUF_BLOCK_READY_FOR_USE: + state_str = "READY_FOR_USE"; + break; + case BUF_BLOCK_FILE_PAGE: + state_str = "FILE_PAGE"; + break; + case BUF_BLOCK_MEMORY: + state_str = "MEMORY"; + break; + case BUF_BLOCK_REMOVE_HASH: + state_str = "REMOVE_HASH"; + break; + }; + + OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE], + state_str)); + + switch (page_info->io_fix) { + case BUF_IO_NONE: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_NONE")); + break; + case BUF_IO_READ: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_READ")); + break; + case BUF_IO_WRITE: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_WRITE")); + break; + case BUF_IO_PIN: + OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX], + "IO_PIN")); + break; + } + + OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD], + (page_info->is_old) ? "YES" : "NO")); + + OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store( + page_info->freed_page_clock)); + + if (schema_table_store_record(thd, table)) { + DBUG_RETURN(1); + } + } + + DBUG_RETURN(0); +} + +/*******************************************************************//** +Set appropriate page type to a buf_page_info_t structure */ +static +void +i_s_innodb_set_page_type( +/*=====================*/ + buf_page_info_t*page_info, /*!< in/out: structure to fill with + scanned info */ + ulint page_type, /*!< in: page type */ + const byte* frame) /*!< in: buffer frame */ +{ + if (page_type == FIL_PAGE_INDEX) { + const page_t* page = (const page_t*) frame; + + /* FIL_PAGE_INDEX is a bit special, its value + is defined as 17855, so we cannot use FIL_PAGE_INDEX + to index into i_s_page_type[] array, its array index + in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX + (1) */ + page_info->page_type = I_S_PAGE_TYPE_INDEX; + + page_info->index_id = btr_page_get_index_id(page); + + page_info->data_size = (ulint)(page_header_get_field( + page, PAGE_HEAP_TOP) - (page_is_comp(page) + ? PAGE_NEW_SUPREMUM_END + : PAGE_OLD_SUPREMUM_END) + - page_header_get_field(page, PAGE_GARBAGE)); + + page_info->num_recs = page_get_n_recs(page); + } else if (page_type >= I_S_PAGE_TYPE_UNKNOWN) { + /* Encountered an unknown page type */ + page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; + } else { + /* Make sure we get the right index into the + i_s_page_type[] array */ + ut_a(page_type == i_s_page_type[page_type].type_value); + + page_info->page_type = page_type; + } + + if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB + || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) { + page_info->page_num = mach_read_from_4( + frame + FIL_PAGE_OFFSET); + page_info->space_id = mach_read_from_4( + frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + } +} +/*******************************************************************//** +Scans pages in the buffer cache, and collect their general information +into the buf_page_info_t array which is zero-filled. So any fields +that are not initialized in the function will default to 0 */ +static +void +i_s_innodb_buffer_page_get_info( +/*============================*/ + const buf_page_t*bpage, /*!< in: buffer pool page to scan */ + ulint pool_id, /*!< in: buffer pool id */ + ulint pos, /*!< in: buffer block position in + buffer pool or in the LRU list */ + buf_page_info_t*page_info) /*!< in: zero filled info structure; + out: structure filled with scanned + info */ +{ + ut_ad(pool_id < MAX_BUFFER_POOLS); + + page_info->pool_id = pool_id; + + page_info->block_id = pos; + + page_info->page_state = buf_page_get_state(bpage); + + /* Only fetch information for buffers that map to a tablespace, + that is, buffer page with state BUF_BLOCK_ZIP_PAGE, + BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */ + if (buf_page_in_file(bpage)) { + const byte* frame; + ulint page_type; + + page_info->space_id = buf_page_get_space(bpage); + + page_info->page_num = buf_page_get_page_no(bpage); + + page_info->flush_type = bpage->flush_type; + + page_info->fix_count = bpage->buf_fix_count; + + page_info->newest_mod = bpage->newest_modification; + + page_info->oldest_mod = bpage->oldest_modification; + + page_info->access_time = bpage->access_time; + + page_info->zip_ssize = bpage->zip.ssize; + + page_info->io_fix = bpage->io_fix; + + page_info->is_old = bpage->old; + + page_info->freed_page_clock = bpage->freed_page_clock; + + if (page_info->page_state == BUF_BLOCK_FILE_PAGE) { + const buf_block_t*block; + + block = reinterpret_cast<const buf_block_t*>(bpage); + frame = block->frame; + page_info->hashed = (block->index != NULL); + } else { + ut_ad(page_info->zip_ssize); + frame = bpage->zip.data; + } + + page_type = fil_page_get_type(frame); + + i_s_innodb_set_page_type(page_info, page_type, frame); + } else { + page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; + } +} + +/*******************************************************************//** +This is the function that goes through each block of the buffer pool +and fetch information to information schema tables: INNODB_BUFFER_PAGE. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_fill_buffer_pool( +/*========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + buf_pool_t* buf_pool, /*!< in: buffer pool to scan */ + const ulint pool_id) /*!< in: buffer pool id */ +{ + int status = 0; + mem_heap_t* heap; + + DBUG_ENTER("i_s_innodb_fill_buffer_pool"); + + heap = mem_heap_create(10000); + + /* Go through each chunk of buffer pool. Currently, we only + have one single chunk for each buffer pool */ + for (ulint n = 0; n < buf_pool->n_chunks; n++) { + const buf_block_t* block; + ulint n_blocks; + buf_page_info_t* info_buffer; + ulint num_page; + ulint mem_size; + ulint chunk_size; + ulint num_to_process = 0; + ulint block_id = 0; + + /* Get buffer block of the nth chunk */ + block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size); + num_page = 0; + + while (chunk_size > 0) { + /* we cache maximum MAX_BUF_INFO_CACHED number of + buffer page info */ + num_to_process = ut_min(chunk_size, + MAX_BUF_INFO_CACHED); + + mem_size = num_to_process * sizeof(buf_page_info_t); + + /* For each chunk, we'll pre-allocate information + structures to cache the page information read from + the buffer pool. Doing so before obtain any mutex */ + info_buffer = (buf_page_info_t*) mem_heap_zalloc( + heap, mem_size); + + /* Obtain appropriate mutexes. Since this is diagnostic + buffer pool info printout, we are not required to + preserve the overall consistency, so we can + release mutex periodically */ + buf_pool_mutex_enter(buf_pool); + + /* GO through each block in the chunk */ + for (n_blocks = num_to_process; n_blocks--; block++) { + i_s_innodb_buffer_page_get_info( + &block->page, pool_id, block_id, + info_buffer + num_page); + block_id++; + num_page++; + } + + buf_pool_mutex_exit(buf_pool); + + /* Fill in information schema table with information + just collected from the buffer chunk scan */ + status = i_s_innodb_buffer_page_fill( + thd, tables, info_buffer, + num_page, heap); + + /* If something goes wrong, break and return */ + if (status) { + break; + } + + mem_heap_empty(heap); + chunk_size -= num_to_process; + num_page = 0; + } + } + + mem_heap_free(heap); + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Fill page information for pages in InnoDB buffer pool to the +dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_fill_table( +/*==============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + + DBUG_ENTER("i_s_innodb_buffer_page_fill_table"); + + /* deny access to user without PROCESS privilege */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + /* Walk through each buffer pool */ + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool; + + buf_pool = buf_pool_from_array(i); + + /* Fetch information from pages in this buffer pool, + and fill the corresponding I_S table */ + status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i); + + /* If something wrong, break and return */ + if (status) { + break; + } + } + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_init( +/*========================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_page_init"); + + schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p); + + schema->fields_info = i_s_innodb_buffer_page_fields_info; + schema->fill_table = i_s_innodb_buffer_page_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_PAGE"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Page Information"), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_page_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), +}; + +static ST_FIELD_INFO i_s_innodb_buf_page_lru_fields_info[] = +{ +#define IDX_BUF_LRU_POOL_ID 0 + {STRUCT_FLD(field_name, "POOL_ID"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_POS 1 + {STRUCT_FLD(field_name, "LRU_POSITION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_SPACE 2 + {STRUCT_FLD(field_name, "SPACE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NUM 3 + {STRUCT_FLD(field_name, "PAGE_NUMBER"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_TYPE 4 + {STRUCT_FLD(field_name, "PAGE_TYPE"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FLUSH_TYPE 5 + {STRUCT_FLD(field_name, "FLUSH_TYPE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FIX_COUNT 6 + {STRUCT_FLD(field_name, "FIX_COUNT"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_HASHED 7 + {STRUCT_FLD(field_name, "IS_HASHED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NEWEST_MOD 8 + {STRUCT_FLD(field_name, "NEWEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_OLDEST_MOD 9 + {STRUCT_FLD(field_name, "OLDEST_MODIFICATION"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_ACCESS_TIME 10 + {STRUCT_FLD(field_name, "ACCESS_TIME"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_TABLE_NAME 11 + {STRUCT_FLD(field_name, "TABLE_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_INDEX_NAME 12 + {STRUCT_FLD(field_name, "INDEX_NAME"), + STRUCT_FLD(field_length, 1024), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_NUM_RECS 13 + {STRUCT_FLD(field_name, "NUMBER_RECORDS"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_DATA_SIZE 14 + {STRUCT_FLD(field_name, "DATA_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_ZIP_SIZE 15 + {STRUCT_FLD(field_name, "COMPRESSED_SIZE"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_STATE 16 + {STRUCT_FLD(field_name, "COMPRESSED"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_IO_FIX 17 + {STRUCT_FLD(field_name, "IO_FIX"), + STRUCT_FLD(field_length, 64), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_IS_OLD 18 + {STRUCT_FLD(field_name, "IS_OLD"), + STRUCT_FLD(field_length, 3), + STRUCT_FLD(field_type, MYSQL_TYPE_STRING), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + +#define IDX_BUF_LRU_PAGE_FREE_CLOCK 19 + {STRUCT_FLD(field_name, "FREE_PAGE_CLOCK"), + STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS), + STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG), + STRUCT_FLD(value, 0), + STRUCT_FLD(field_flags, MY_I_S_UNSIGNED), + STRUCT_FLD(old_name, ""), + STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}, + + END_OF_ST_FIELD_INFO +}; + +/*******************************************************************//** +Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information +cached in the buf_page_info_t array +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buf_page_lru_fill( +/*=========================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + const buf_page_info_t* info_array, /*!< in: array cached page + info */ + ulint num_page) /*!< in: number of page info + cached */ +{ + TABLE* table; + Field** fields; + mem_heap_t* heap; + + DBUG_ENTER("i_s_innodb_buf_page_lru_fill"); + + table = tables->table; + + fields = table->field; + + heap = mem_heap_create(1000); + + /* Iterate through the cached array and fill the I_S table rows */ + for (ulint i = 0; i < num_page; i++) { + const buf_page_info_t* page_info; + const char* table_name; + const char* index_name; + const char* state_str; + enum buf_page_state state; + + table_name = NULL; + index_name = NULL; + state_str = NULL; + + page_info = info_array + i; + + OK(fields[IDX_BUF_LRU_POOL_ID]->store(page_info->pool_id)); + + OK(fields[IDX_BUF_LRU_POS]->store(page_info->block_id)); + + OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(page_info->space_id)); + + OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(page_info->page_num)); + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_TYPE], + i_s_page_type[page_info->page_type].type_str)); + + OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store( + page_info->flush_type)); + + OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store( + page_info->fix_count)); + + if (page_info->hashed) { + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_HASHED], "YES")); + } else { + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_HASHED], "NO")); + } + + OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store( + page_info->newest_mod, true)); + + OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store( + page_info->oldest_mod, true)); + + OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store( + page_info->access_time)); + + /* If this is an index page, fetch the index name + and table name */ + if (page_info->page_type == I_S_PAGE_TYPE_INDEX) { + const dict_index_t* index; + + mutex_enter(&dict_sys->mutex); + index = dict_index_get_if_in_cache_low( + page_info->index_id); + + /* Copy the index/table name under mutex. We + do not want to hold the InnoDB mutex while + filling the IS table */ + if (index) { + const char* name_ptr = index->name; + + if (name_ptr[0] == TEMP_INDEX_PREFIX) { + name_ptr++; + } + + index_name = mem_heap_strdup(heap, name_ptr); + + table_name = mem_heap_strdup(heap, + index->table_name); + } + + mutex_exit(&dict_sys->mutex); + } + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_TABLE_NAME], table_name)); + + OK(field_store_string( + fields[IDX_BUF_LRU_PAGE_INDEX_NAME], index_name)); + OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store( + page_info->num_recs)); + + OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store( + page_info->data_size)); + + OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store( + page_info->zip_ssize ? + 512 << page_info->zip_ssize : 0)); + + state = static_cast<enum buf_page_state>(page_info->page_state); + + switch (state) { + /* Compressed page */ + case BUF_BLOCK_ZIP_PAGE: + case BUF_BLOCK_ZIP_DIRTY: + state_str = "YES"; + break; + /* Uncompressed page */ + case BUF_BLOCK_FILE_PAGE: + state_str = "NO"; + break; + /* We should not see following states */ + case BUF_BLOCK_ZIP_FREE: + case BUF_BLOCK_READY_FOR_USE: + case BUF_BLOCK_NOT_USED: + case BUF_BLOCK_MEMORY: + case BUF_BLOCK_REMOVE_HASH: + state_str = NULL; + break; + }; + + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE], + state_str)); + + switch (page_info->io_fix) { + case BUF_IO_NONE: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_NONE")); + break; + case BUF_IO_READ: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_READ")); + break; + case BUF_IO_WRITE: + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX], + "IO_WRITE")); + break; + } + + OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD], + (page_info->is_old) ? "YES" : "NO")); + + OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store( + page_info->freed_page_clock)); + + if (schema_table_store_record(thd, table)) { + mem_heap_free(heap); + DBUG_RETURN(1); + } + + mem_heap_empty(heap); + } + + mem_heap_free(heap); + + DBUG_RETURN(0); +} + +/*******************************************************************//** +This is the function that goes through buffer pool's LRU list +and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_fill_buffer_lru( +/*=======================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + buf_pool_t* buf_pool, /*!< in: buffer pool to scan */ + const ulint pool_id) /*!< in: buffer pool id */ +{ + int status = 0; + buf_page_info_t* info_buffer; + ulint lru_pos = 0; + const buf_page_t* bpage; + ulint lru_len; + + DBUG_ENTER("i_s_innodb_fill_buffer_lru"); + + /* Obtain buf_pool mutex before allocate info_buffer, since + UT_LIST_GET_LEN(buf_pool->LRU) could change */ + buf_pool_mutex_enter(buf_pool); + + lru_len = UT_LIST_GET_LEN(buf_pool->LRU); + + /* Print error message if malloc fail */ + info_buffer = (buf_page_info_t*) my_malloc( + lru_len * sizeof *info_buffer, MYF(MY_WME)); + + if (!info_buffer) { + status = 1; + goto exit; + } + + memset(info_buffer, 0, lru_len * sizeof *info_buffer); + + /* Walk through Pool's LRU list and print the buffer page + information */ + bpage = UT_LIST_GET_LAST(buf_pool->LRU); + + while (bpage != NULL) { + /* Use the same function that collect buffer info for + INNODB_BUFFER_PAGE to get buffer page info */ + i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos, + (info_buffer + lru_pos)); + + bpage = UT_LIST_GET_PREV(LRU, bpage); + + lru_pos++; + } + + ut_ad(lru_pos == lru_len); + ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU)); + +exit: + buf_pool_mutex_exit(buf_pool); + + if (info_buffer) { + status = i_s_innodb_buf_page_lru_fill( + thd, tables, info_buffer, lru_len); + + my_free(info_buffer); + } + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Fill page information for pages in InnoDB buffer pool to the +dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buf_page_lru_fill_table( +/*===============================*/ + THD* thd, /*!< in: thread */ + TABLE_LIST* tables, /*!< in/out: tables to fill */ + Item* ) /*!< in: condition (ignored) */ +{ + int status = 0; + + DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table"); + + /* deny access to any users that do not hold PROCESS_ACL */ + if (check_global_access(thd, PROCESS_ACL)) { + DBUG_RETURN(0); + } + + /* Walk through each buffer pool */ + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_pool_t* buf_pool; + + buf_pool = buf_pool_from_array(i); + + /* Fetch information from pages in this buffer pool's LRU list, + and fill the corresponding I_S table */ + status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i); + + /* If something wrong, break and return */ + if (status) { + break; + } + } + + DBUG_RETURN(status); +} + +/*******************************************************************//** +Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU. +@return 0 on success, 1 on failure */ +static +int +i_s_innodb_buffer_page_lru_init( +/*============================*/ + void* p) /*!< in/out: table schema object */ +{ + ST_SCHEMA_TABLE* schema; + + DBUG_ENTER("i_s_innodb_buffer_page_lru_init"); + + schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p); + + schema->fields_info = i_s_innodb_buf_page_lru_fields_info; + schema->fill_table = i_s_innodb_buf_page_lru_fill_table; + + DBUG_RETURN(0); +} + +UNIV_INTERN struct st_mysql_plugin i_s_innodb_buffer_page_lru = +{ + /* the plugin type (a MYSQL_XXX_PLUGIN value) */ + /* int */ + STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN), + + /* pointer to type-specific plugin descriptor */ + /* void* */ + STRUCT_FLD(info, &i_s_info), + + /* plugin name */ + /* const char* */ + STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"), + + /* plugin author (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(author, plugin_author), + + /* general descriptive text (for SHOW PLUGINS) */ + /* const char* */ + STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"), + + /* the plugin license (PLUGIN_LICENSE_XXX) */ + /* int */ + STRUCT_FLD(license, PLUGIN_LICENSE_GPL), + + /* the function to invoke when plugin is loaded */ + /* int (*)(void*); */ + STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init), + + /* the function to invoke when plugin is unloaded */ + /* int (*)(void*); */ + STRUCT_FLD(deinit, i_s_common_deinit), + + /* plugin version (for SHOW PLUGINS) */ + /* unsigned int */ + STRUCT_FLD(version, INNODB_VERSION_SHORT), + + /* struct st_mysql_show_var* */ + STRUCT_FLD(status_vars, NULL), + + /* struct st_mysql_sys_var** */ + STRUCT_FLD(system_vars, NULL), + + /* reserved for dependency checking */ + /* void* */ + STRUCT_FLD(__reserved1, NULL), + + /* Plugin flags */ + /* unsigned long */ + STRUCT_FLD(flags, 0UL), +}; + /*******************************************************************//** Unbind a dynamic INFORMATION_SCHEMA table. @return 0 on success */ @@ -1807,3 +3658,5 @@ i_s_common_deinit( DBUG_RETURN(0); } + + diff --git a/storage/innobase/handler/i_s.h b/storage/innobase/handler/i_s.h index dc0deef119b..6b95ce25b58 100644 --- a/storage/innobase/handler/i_s.h +++ b/storage/innobase/handler/i_s.h @@ -35,5 +35,8 @@ extern struct st_mysql_plugin i_s_innodb_cmp; extern struct st_mysql_plugin i_s_innodb_cmp_reset; extern struct st_mysql_plugin i_s_innodb_cmpmem; extern struct st_mysql_plugin i_s_innodb_cmpmem_reset; +extern struct st_mysql_plugin i_s_innodb_buffer_page; +extern struct st_mysql_plugin i_s_innodb_buffer_page_lru; +extern struct st_mysql_plugin i_s_innodb_buffer_stats;; #endif /* i_s_h */ diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index e534e165c0c..c7887afef92 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -3604,11 +3604,18 @@ bitmap_fail: root = ibuf_tree_root_get(&mtr); - err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG - | BTR_NO_UNDO_LOG_FLAG, - cursor, - ibuf_entry, &ins_rec, - &dummy_big_rec, 0, thr, &mtr); + err = btr_cur_optimistic_insert( + BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG, + cursor, ibuf_entry, &ins_rec, + &dummy_big_rec, 0, thr, &mtr); + + if (err == DB_FAIL) { + err = btr_cur_pessimistic_insert( + BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG, + cursor, ibuf_entry, &ins_rec, + &dummy_big_rec, 0, thr, &mtr); + } + mutex_exit(&ibuf_pessimistic_insert_mutex); ibuf_size_update(root, &mtr); mutex_exit(&ibuf_mutex); diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index a39592943d8..fd8620eab3b 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -68,7 +68,10 @@ Created 11/5/1995 Heikki Tuuri position of the block. */ /* @} */ -#define MAX_BUFFER_POOLS 64 /*!< The maximum number of buffer +#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing + a buffer pool ID */ +#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS) + /*!< The maximum number of buffer pools that can be defined */ #define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent @@ -758,6 +761,18 @@ void buf_print_io( /*=========*/ FILE* file); /*!< in: file where to print */ +/*******************************************************************//** +Collect buffer pool stats information for a buffer pool. Also +record aggregated stats if there are more than one buffer pool +in the server */ +UNIV_INTERN +void +buf_stats_get_pool_info( +/*====================*/ + buf_pool_t* buf_pool, /*!< in: buffer pool */ + ulint pool_id, /*!< in: buffer pool ID */ + buf_pool_info_t* all_pool_info); /*!< in/out: buffer pool info + to fill */ /*********************************************************************//** Returns the ratio in percents of modified pages in the buffer pool / database pages in the buffer pool. @@ -1325,12 +1340,25 @@ void buf_get_total_stat( /*===============*/ buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */ +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size); /*!< in: chunk size */ #endif /* !UNIV_HOTBACKUP */ /** The common buffer control block structure for compressed and uncompressed frames */ +/** Number of bits used for buffer page states. */ +#define BUF_PAGE_STATE_BITS 3 + struct buf_page_struct{ /** @name General fields None of these bit-fields must be modified without holding @@ -1345,7 +1373,8 @@ struct buf_page_struct{ unsigned offset:32; /*!< page number; also protected by buf_pool->mutex. */ - unsigned state:3; /*!< state of the control block; also + 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 diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 0d9687e6b2a..84c0ab9d610 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -36,6 +36,15 @@ Created 11/5/1995 Heikki Tuuri #include "buf0lru.h" #include "buf0rea.h" +/** A chunk of buffers. The buffer pool is allocated in chunks. */ +struct buf_chunk_struct{ + ulint mem_size; /*!< allocated size of the chunk */ + ulint size; /*!< size of frames[] and blocks[] */ + void* mem; /*!< pointer to the memory area which + was allocated for the frames */ + buf_block_t* blocks; /*!< array of buffer control blocks */ +}; + /*********************************************************************//** Gets the current size of buffer buf_pool in bytes. @return size in bytes */ @@ -1276,4 +1285,21 @@ buf_pool_mutex_exit_all(void) buf_pool_mutex_exit(buf_pool); } } +/*********************************************************************//** +Get the nth chunk's buffer block in the specified buffer pool. +@return the nth chunk's buffer block. */ +UNIV_INLINE +buf_block_t* +buf_get_nth_chunk_block( +/*====================*/ + const buf_pool_t* buf_pool, /*!< in: buffer pool instance */ + ulint n, /*!< in: nth chunk in the buffer pool */ + ulint* chunk_size) /*!< in: chunk size */ +{ + const buf_chunk_t* chunk; + + chunk = buf_pool->chunks + n; + *chunk_size = chunk->size; + return(chunk->blocks); +} #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 610bd4b0e5c..ed47ccff052 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -142,6 +142,8 @@ extern fil_addr_t fil_addr_null; #define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */ #define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */ +#define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_ZBLOB2 + /*!< Last page type */ /* @} */ /** Space types @{ */ diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 0b8d7b6fa03..f280deeee77 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -41,6 +41,9 @@ Created 12/9/1995 Heikki Tuuri #include "sync0rw.h" #endif /* !UNIV_HOTBACKUP */ +/* Type used for all log sequence number storage and arithmetics */ +typedef ib_uint64_t lsn_t; + /** Redo log buffer */ typedef struct log_struct log_t; /** Redo log group */ diff --git a/storage/innobase/page/page0cur.c b/storage/innobase/page/page0cur.c index d49b121afab..55ba72b4fe9 100644 --- a/storage/innobase/page/page0cur.c +++ b/storage/innobase/page/page0cur.c @@ -1902,6 +1902,7 @@ page_cur_delete_rec( /* Save to local variables some data associated with current_rec */ cur_slot_no = page_dir_find_owner_slot(current_rec); + ut_ad(cur_slot_no > 0); cur_dir_slot = page_dir_get_nth_slot(page, cur_slot_no); cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot); diff --git a/storage/innobase/page/page0page.c b/storage/innobase/page/page0page.c index 5f0380cb55f..78135b0aff2 100644 --- a/storage/innobase/page/page0page.c +++ b/storage/innobase/page/page0page.c @@ -781,17 +781,23 @@ page_copy_rec_list_start( if (UNIV_LIKELY_NULL(new_page_zip)) { mtr_set_log_mode(mtr, log_mode); + DBUG_EXECUTE_IF("page_copy_rec_list_start_compress_fail", + goto zip_reorganize;); + if (UNIV_UNLIKELY (!page_zip_compress(new_page_zip, new_page, index, mtr))) { + ulint ret_pos; +#ifndef DBUG_OFF +zip_reorganize: +#endif /* DBUG_OFF */ /* Before trying to reorganize the page, store the number of preceding records on the page. */ - ulint ret_pos - = page_rec_get_n_recs_before(ret); + ret_pos = page_rec_get_n_recs_before(ret); /* Before copying, "ret" was the predecessor of the predefined supremum record. If it was the predefined infimum record, then it would - still be the infimum. Thus, the assertion - ut_a(ret_pos > 0) would fail here. */ + still be the infimum, and we would have + ret_pos == 0. */ if (UNIV_UNLIKELY (!page_zip_reorganize(new_block, index, mtr))) { @@ -807,15 +813,10 @@ page_copy_rec_list_start( btr_blob_dbg_add(new_page, index, "copy_start_reorg_fail"); return(NULL); - } else { - /* The page was reorganized: - Seek to ret_pos. */ - ret = new_page + PAGE_NEW_INFIMUM; - - do { - ret = rec_get_next_ptr(ret, TRUE); - } while (--ret_pos); } + + /* The page was reorganized: Seek to ret_pos. */ + ret = page_rec_get_nth(new_page, ret_pos); } } @@ -1051,6 +1052,7 @@ page_delete_rec_list_end( n_owned = rec_get_n_owned_new(rec2) - count; slot_index = page_dir_find_owner_slot(rec2); + ut_ad(slot_index > 0); slot = page_dir_get_nth_slot(page, slot_index); } else { rec_t* rec2 = rec; @@ -1066,6 +1068,7 @@ page_delete_rec_list_end( n_owned = rec_get_n_owned_old(rec2) - count; slot_index = page_dir_find_owner_slot(rec2); + ut_ad(slot_index > 0); slot = page_dir_get_nth_slot(page, slot_index); } @@ -1470,6 +1473,10 @@ page_rec_get_nth_const( ulint n_owned; const rec_t* rec; + if (nth == 0) { + return(page_get_infimum_rec(page)); + } + ut_ad(nth < UNIV_PAGE_SIZE / (REC_N_NEW_EXTRA_BYTES + 1)); for (i = 0;; i++) { diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index 60a66ea3945..18486514267 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -2168,9 +2168,16 @@ row_ins_index_entry_low( goto function_exit; } - err = btr_cur_pessimistic_insert( + + err = btr_cur_optimistic_insert( 0, &cursor, entry, &insert_rec, &big_rec, n_ext, thr, &mtr); + + if (err == DB_FAIL) { + err = btr_cur_pessimistic_insert( + 0, &cursor, entry, &insert_rec, + &big_rec, n_ext, thr, &mtr); + } } } diff --git a/storage/innobase/row/row0merge.c b/storage/innobase/row/row0merge.c index 750f9d72cf2..7c9fb8812e6 100644 --- a/storage/innobase/row/row0merge.c +++ b/storage/innobase/row/row0merge.c @@ -1235,11 +1235,25 @@ row_merge_read_clustered_index( goto err_exit; } + /* Store the cursor position on the last user + record on the page. */ + btr_pcur_move_to_prev_on_page(&pcur); + /* Leaf pages must never be empty, unless + this is the only page in the index tree. */ + ut_ad(btr_pcur_is_on_user_rec(&pcur) + || buf_block_get_page_no( + btr_pcur_get_block(&pcur)) + == clust_index->page); + btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); mtr_start(&mtr); + /* Restore position on the record, or its + predecessor if the record was purged + meanwhile. */ btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr); + /* Move to the successor of the original record. */ has_next = btr_pcur_move_to_next_user_rec(&pcur, &mtr); } |