summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-11-22 11:43:55 +0100
committerSergei Golubchik <sergii@pisem.net>2012-11-22 11:43:55 +0100
commitc499fa1ef391556b0fe12d5a38af5ae674b98a19 (patch)
treed693a3ffa91d8ca10359783b7be5ebfad222eae4
parenta48a91d90f07798deebe514d9d827fb719da7294 (diff)
parentb1b939f4f79ae3eeab5afcd2d3a405009368280f (diff)
downloadmariadb-git-c499fa1ef391556b0fe12d5a38af5ae674b98a19.tar.gz
XtraDB from Percona-Server-5.5.28-rel29.1
-rw-r--r--mysql-test/include/have_innodb.combinations9
-rw-r--r--mysql-test/suite/innodb/t/innodb_information_schema_buffer.test5
-rw-r--r--mysql-test/t/mysqlshow.test2
-rw-r--r--storage/xtradb/btr/btr0btr.c21
-rw-r--r--storage/xtradb/btr/btr0cur.c39
-rw-r--r--storage/xtradb/btr/btr0pcur.c67
-rw-r--r--storage/xtradb/buf/buf0buf.c22
-rw-r--r--storage/xtradb/buf/buf0lru.c2
-rw-r--r--storage/xtradb/buf/buf0rea.c4
-rw-r--r--storage/xtradb/handler/ha_innodb.cc341
-rw-r--r--storage/xtradb/handler/i_s.cc1836
-rw-r--r--storage/xtradb/handler/i_s.h3
-rw-r--r--storage/xtradb/ibuf/ibuf0ibuf.c17
-rw-r--r--storage/xtradb/include/buf0buf.h34
-rw-r--r--storage/xtradb/include/buf0buf.ic19
-rw-r--r--storage/xtradb/include/fil0fil.h2
-rw-r--r--storage/xtradb/include/ha_prototypes.h2
-rw-r--r--storage/xtradb/include/log0log.h3
-rw-r--r--storage/xtradb/include/os0proc.h3
-rw-r--r--storage/xtradb/include/srv0srv.h1
-rw-r--r--storage/xtradb/include/trx0sys.h16
-rw-r--r--storage/xtradb/include/univ.i2
-rw-r--r--storage/xtradb/os/os0proc.c58
-rw-r--r--storage/xtradb/page/page0page.c21
-rw-r--r--storage/xtradb/row/row0ins.c9
-rw-r--r--storage/xtradb/row/row0merge.c16
-rw-r--r--storage/xtradb/srv/srv0srv.c2
-rw-r--r--storage/xtradb/srv/srv0start.c3
-rw-r--r--storage/xtradb/trx/trx0sys.c132
-rw-r--r--storage/xtradb/trx/trx0trx.c21
30 files changed, 2446 insertions, 266 deletions
diff --git a/mysql-test/include/have_innodb.combinations b/mysql-test/include/have_innodb.combinations
index 117bf2216a1..93c39fd1a98 100644
--- a/mysql-test/include/have_innodb.combinations
+++ b/mysql-test/include/have_innodb.combinations
@@ -4,6 +4,9 @@ plugin-load=$HA_INNODB_SO
innodb
innodb-cmpmem
innodb-trx
+innodb-buffer-pool-stats
+innodb-buffer-page
+innodb-buffer-page-lru
[xtradb_plugin]
ignore-builtin-innodb
@@ -11,8 +14,14 @@ plugin-load=$HA_XTRADB_SO
innodb
innodb-cmpmem
innodb-trx
+innodb-buffer-pool-stats
+innodb-buffer-page
+innodb-buffer-page-lru
[xtradb]
innodb
innodb-cmpmem
innodb-trx
+innodb-buffer-pool-stats
+innodb-buffer-page
+innodb-buffer-page-lru
diff --git a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
index b9c6aecd177..751a2bd6b5e 100644
--- a/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
+++ b/mysql-test/suite/innodb/t/innodb_information_schema_buffer.test
@@ -3,11 +3,6 @@
-- source include/have_innodb.inc
-if (`select plugin_auth_version <= "1.1.8-29.0" from information_schema.plugins where plugin_name='innodb'`)
-{
- --skip Not fixed in XtraDB 1.1.8-29.0 or earlier
-}
-
-- disable_result_log
SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
diff --git a/mysql-test/t/mysqlshow.test b/mysql-test/t/mysqlshow.test
index 2b6b5b631b2..5dba7fa5b85 100644
--- a/mysql-test/t/mysqlshow.test
+++ b/mysql-test/t/mysqlshow.test
@@ -29,7 +29,7 @@ select "---- -v -v -t ------" as "";
DROP TABLE t1, t2;
-if (`select count(*) from information_schema.plugins where plugin_name='innodb' and plugin_auth_version > "1.1.8-29.0"`)
+if (`select count(*) from information_schema.plugins where plugin_name='innodb' and plugin_auth_version > "1.1.8-29.1"`)
{
# because of lp:1066512 this test shows xtradb I_S plugins, even when
# xtradb is supposed to be disabled
diff --git a/storage/xtradb/btr/btr0btr.c b/storage/xtradb/btr/btr0btr.c
index 3f11684cb34..ed97fc5bd58 100644
--- a/storage/xtradb/btr/btr0btr.c
+++ b/storage/xtradb/btr/btr0btr.c
@@ -1891,6 +1891,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 */
@@ -2371,12 +2372,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);
+ }
}
/**************************************************************//**
diff --git a/storage/xtradb/btr/btr0cur.c b/storage/xtradb/btr/btr0cur.c
index 26db7329b7e..61c07ac792e 100644
--- a/storage/xtradb/btr/btr0cur.c
+++ b/storage/xtradb/btr/btr0cur.c
@@ -1412,7 +1412,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;
+ }
}
}
@@ -1548,20 +1553,9 @@ btr_cur_pessimistic_insert(
ut_ad((thr && thr_get_trx(thr)->fake_changes) || 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);
@@ -2188,8 +2182,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))
@@ -2559,7 +2557,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)
@@ -2588,7 +2591,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/xtradb/btr/btr0pcur.c b/storage/xtradb/btr/btr0pcur.c
index 0de7b63f92d..b335e2c8aee 100644
--- a/storage/xtradb/btr/btr0pcur.c
+++ b/storage/xtradb/btr/btr0pcur.c
@@ -354,44 +354,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/xtradb/buf/buf0buf.c b/storage/xtradb/buf/buf0buf.c
index 6ce77372dac..bbc1042ca78 100644
--- a/storage/xtradb/buf/buf0buf.c
+++ b/storage/xtradb/buf/buf0buf.c
@@ -336,15 +336,6 @@ 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. (moved to buf0buf.h)*/
-//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
zero if all modified pages have been flushed to disk.
@@ -1028,7 +1019,8 @@ buf_chunk_init(
/*===========*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
buf_chunk_t* chunk, /*!< out: chunk of buffers */
- ulint mem_size) /*!< in: requested size in bytes */
+ ulint mem_size, /*!< in: requested size in bytes */
+ ibool populate) /*!< in: virtual page preallocation */
{
buf_block_t* block;
byte* frame;
@@ -1044,7 +1036,7 @@ buf_chunk_init(
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
chunk->mem_size = mem_size;
- chunk->mem = os_mem_alloc_large(&chunk->mem_size);
+ chunk->mem = os_mem_alloc_large(&chunk->mem_size, populate);
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
@@ -1254,6 +1246,7 @@ buf_pool_init_instance(
/*===================*/
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
ulint buf_pool_size, /*!< in: size in bytes */
+ ibool populate, /*!< in: virtual page preallocation */
ulint instance_no) /*!< in: id of the instance */
{
ulint i;
@@ -1286,7 +1279,7 @@ buf_pool_init_instance(
UT_LIST_INIT(buf_pool->free);
- if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
+ if (!buf_chunk_init(buf_pool, chunk, buf_pool_size, populate)) {
mem_free(chunk);
mem_free(buf_pool);
@@ -1381,6 +1374,7 @@ ulint
buf_pool_init(
/*==========*/
ulint total_size, /*!< in: size of the total pool in bytes */
+ ibool populate, /*!< in: virtual page preallocation */
ulint n_instances) /*!< in: number of instances */
{
ulint i;
@@ -1398,7 +1392,7 @@ buf_pool_init(
for (i = 0; i < n_instances; i++) {
buf_pool_t* ptr = &buf_pool_ptr[i];
- if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
+ if (buf_pool_init_instance(ptr, size, populate, i) != DB_SUCCESS) {
/* Free all the instances created so far. */
buf_pool_free(i);
@@ -4973,7 +4967,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/xtradb/buf/buf0lru.c b/storage/xtradb/buf/buf0lru.c
index e8300107f3d..a6a1f8dcf9c 100644
--- a/storage/xtradb/buf/buf0lru.c
+++ b/storage/xtradb/buf/buf0lru.c
@@ -2384,7 +2384,7 @@ buf_LRU_free_one_page(
#endif
mutex_t* block_mutex = buf_page_get_mutex(bpage);
- ut_ad(buf_pool_mutex_own(buf_pool));
+ ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
ut_ad(mutex_own(block_mutex));
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
diff --git a/storage/xtradb/buf/buf0rea.c b/storage/xtradb/buf/buf0rea.c
index c29dcbf0444..67379d614a0 100644
--- a/storage/xtradb/buf/buf0rea.c
+++ b/storage/xtradb/buf/buf0rea.c
@@ -64,7 +64,7 @@ buf_read_page_handle_error(
== BUF_BLOCK_FILE_PAGE);
/* First unfix and release lock on the bpage */
- buf_pool_mutex_enter(buf_pool);
+ mutex_enter(&buf_pool->LRU_list_mutex);
mutex_enter(buf_page_get_mutex(bpage));
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
ut_ad(bpage->buf_fix_count == 0);
@@ -85,7 +85,7 @@ buf_read_page_handle_error(
buf_pool->n_pend_reads--;
mutex_exit(buf_page_get_mutex(bpage));
- buf_pool_mutex_exit(buf_pool);
+ mutex_exit(&buf_pool->LRU_list_mutex);
}
/********************************************************************//**
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 32ec2d9d858..5cf3b021510 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -874,7 +874,7 @@ extern "C" UNIV_INTERN
ibool
thd_is_replication_slave_thread(
/*============================*/
- void* thd) /*!< in: thread handle (THD*) */
+ const void* thd) /*!< in: thread handle (THD*) */
{
return((ibool) thd_slave_thread((THD*) thd));
}
@@ -2465,6 +2465,122 @@ ha_innobase::init_table_handle_for_HANDLER(void)
reset_template();
}
+#ifdef HAVE_REPLICATION
+/* The last read master log coordinates in the slave info file */
+static char master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
+static int master_log_pos;
+/* The slave relay log coordinates in the slave info file after startup */
+static char original_relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
+static int original_relay_log_pos;
+/* The master log coordinates in the slave info file after startup */
+static char original_master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
+static int original_master_log_pos;
+#endif
+
+/*****************************************************************//**
+Overwrites the MySQL relay log info file with the current master and relay log
+coordinates from InnoDB. Skips overwrite if the master log position did not
+change from the last overwrite. If the InnoDB master log position is equal
+to position that was read from the info file on startup before any overwrites,
+restores the original positions. */
+static
+void
+innobase_do_overwrite_relay_log_info(void)
+/*======================================*/
+{
+#ifdef HAVE_REPLICATION
+ char info_fname[FN_REFLEN];
+ File info_fd = -1;
+ int error = 0;
+ char buff[FN_REFLEN*2+22*2+4];
+ char *relay_info_log_pos;
+ size_t buf_len;
+
+ if (master_log_fname[0] == '\0') {
+ fprintf(stderr,
+ "InnoDB: something wrong with relay-log.info. "
+ "InnoDB will not overwrite it.\n");
+ return;
+ }
+
+ if (strcmp(master_log_fname, trx_sys_mysql_master_log_name) == 0
+ && master_log_pos == trx_sys_mysql_master_log_pos) {
+ fprintf(stderr,
+ "InnoDB: InnoDB and relay-log.info are synchronized. "
+ "InnoDB will not overwrite it.\n");
+ return;
+ }
+
+ /* If we overwrite the file back to the original master log position,
+ restore the original relay log position too. This is required because
+ we might have rolled back a prepared transaction and restored the
+ original master log position from the InnoDB trx sys header, but the
+ corresponding relay log position points to an already-purged file. */
+ if (strcmp(original_master_log_fname, trx_sys_mysql_master_log_name)
+ == 0
+ && (original_master_log_pos == trx_sys_mysql_master_log_pos)) {
+
+ strncpy(trx_sys_mysql_relay_log_name, original_relay_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ trx_sys_mysql_relay_log_pos = original_relay_log_pos;
+ }
+
+ fn_format(info_fname, relay_log_info_file, mysql_data_home, "",
+ MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH);
+
+ if (access(info_fname, F_OK)) {
+ /* File does not exist */
+ error = 1;
+ goto skip_overwrite;
+ }
+
+ /* File exists */
+ info_fd = my_open(info_fname, O_RDWR|O_BINARY, MYF(MY_WME));
+ if (info_fd < 0) {
+ error = 1;
+ goto skip_overwrite;
+ }
+
+ relay_info_log_pos = strmov(buff, trx_sys_mysql_relay_log_name);
+ *relay_info_log_pos ++= '\n';
+ relay_info_log_pos = longlong2str(trx_sys_mysql_relay_log_pos,
+ relay_info_log_pos, 10);
+ *relay_info_log_pos ++= '\n';
+ relay_info_log_pos = strmov(relay_info_log_pos,
+ trx_sys_mysql_master_log_name);
+ *relay_info_log_pos ++= '\n';
+ relay_info_log_pos = longlong2str(trx_sys_mysql_master_log_pos,
+ relay_info_log_pos, 10);
+ *relay_info_log_pos = '\n';
+
+ buf_len = (relay_info_log_pos - buff) + 1;
+ if (my_write(info_fd, (uchar *)buff, buf_len, MY_WME) != buf_len) {
+ error = 1;
+ } else if (my_sync(info_fd, MY_WME)) {
+ error = 1;
+ }
+
+ if (info_fd >= 0) {
+ my_close(info_fd, MYF(0));
+ }
+
+ strncpy(master_log_fname, trx_sys_mysql_relay_log_name,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ master_log_pos = trx_sys_mysql_master_log_pos;
+
+skip_overwrite:
+ if (error) {
+ fprintf(stderr,
+ "InnoDB: ERROR: error occured during overwriting "
+ "relay-log.info.\n");
+ } else {
+ fprintf(stderr,
+ "InnoDB: relay-log.info was overwritten.\n");
+ }
+#endif
+}
+
+
/*********************************************************************//**
Opens an InnoDB database.
@return 0 on success, error code on failure */
@@ -2598,12 +2714,13 @@ innobase_init(
#ifdef HAVE_REPLICATION
#ifdef MYSQL_SERVER
/* read master log position from relay-log.info if exists */
- char fname[FN_REFLEN+128];
- int pos;
+ char info_fname[FN_REFLEN];
+ char relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
+ int relay_log_pos;
int info_fd;
IO_CACHE info_file;
- fname[0] = '\0';
+ info_fname[0] = '\0';
if(innobase_overwrite_relay_log_info) {
@@ -2612,13 +2729,14 @@ innobase_init(
" Updates by other storage engines may not be synchronized.\n");
bzero((char*) &info_file, sizeof(info_file));
- fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
+ fn_format(info_fname, relay_log_info_file, mysql_data_home, "", 4+32);
int error=0;
- if (!access(fname,F_OK)) {
+ if (!access(info_fname,F_OK)) {
/* exist */
- if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
+ if ((info_fd = my_open(info_fname, O_RDWR | O_BINARY,
+ MYF(MY_WME))) < 0) {
error=1;
} else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
READ_CACHE, 0L, 0, MYF(MY_WME))) {
@@ -2629,16 +2747,18 @@ innobase_init(
relay_info_error:
if (info_fd >= 0)
my_close(info_fd, MYF(0));
- fname[0] = '\0';
+ master_log_fname[0] = '\0';
goto skip_relay;
}
} else {
- fname[0] = '\0';
+ master_log_fname[0] = '\0';
goto skip_relay;
}
- if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
- init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
+ if (init_strvar_from_file(relay_log_fname, sizeof(relay_log_fname),
+ &info_file, "")
+ || /* dummy (it is relay-log) */ init_intvar_from_file(
+ &relay_log_pos, &info_file, BIN_LOG_HEADER_SIZE)) {
end_io_cache(&info_file);
error=1;
goto relay_info_error;
@@ -2647,13 +2767,19 @@ relay_info_error:
fprintf(stderr,
"InnoDB: relay-log.info is detected.\n"
"InnoDB: relay log: position %u, file name %s\n",
- pos, fname);
+ relay_log_pos, relay_log_fname);
+
+ strncpy(trx_sys_mysql_relay_log_name, relay_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ trx_sys_mysql_relay_log_pos = (ib_int64_t) relay_log_pos;
- strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
- trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
+ strncpy(original_relay_log_fname, relay_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ original_relay_log_pos = relay_log_pos;
- if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
- init_intvar_from_file(&pos, &info_file, 0)) {
+ if (init_strvar_from_file(master_log_fname, sizeof(master_log_fname),
+ &info_file, "")
+ || init_intvar_from_file(&master_log_pos, &info_file, 0)) {
end_io_cache(&info_file);
error=1;
goto relay_info_error;
@@ -2661,10 +2787,15 @@ relay_info_error:
fprintf(stderr,
"InnoDB: master log: position %u, file name %s\n",
- pos, fname);
+ master_log_pos, master_log_fname);
+
+ strncpy(trx_sys_mysql_master_log_name, master_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ trx_sys_mysql_master_log_pos = (ib_int64_t) master_log_pos;
- strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
- trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
+ strncpy(original_master_log_fname, master_log_fname,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ original_master_log_pos = master_log_pos;
end_io_cache(&info_file);
if (info_fd >= 0)
@@ -2999,75 +3130,9 @@ innobase_change_buffering_inited_ok:
goto mem_free_and_error;
}
-#ifdef HAVE_REPLICATION
-#ifdef MYSQL_SERVER
if(innobase_overwrite_relay_log_info) {
- /* If InnoDB progressed from relay-log.info, overwrite it */
- if (fname[0] == '\0') {
- fprintf(stderr,
- "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
- } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
- || pos != trx_sys_mysql_master_log_pos) {
- /* Overwrite relay-log.info */
- bzero((char*) &info_file, sizeof(info_file));
- fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
-
- int error = 0;
-
- if (!access(fname,F_OK)) {
- /* exist */
- if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
- error = 1;
- } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
- WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
- error = 1;
- }
-
- if (error) {
- if (info_fd >= 0)
- my_close(info_fd, MYF(0));
- goto skip_overwrite;
- }
- } else {
- error = 1;
- goto skip_overwrite;
- }
-
- char buff[FN_REFLEN*2+22*2+4], *pos;
-
- my_b_seek(&info_file, 0L);
- pos=strmov(buff, trx_sys_mysql_relay_log_name);
- *pos++='\n';
- pos=longlong10_to_str(trx_sys_mysql_relay_log_pos, pos, 10);
- *pos++='\n';
- pos=strmov(pos, trx_sys_mysql_master_log_name);
- *pos++='\n';
- pos=longlong10_to_str(trx_sys_mysql_master_log_pos, pos, 10);
- *pos='\n';
-
- if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
- error = 1;
- if (flush_io_cache(&info_file))
- error = 1;
-
- end_io_cache(&info_file);
- if (info_fd >= 0)
- my_close(info_fd, MYF(0));
-skip_overwrite:
- if (error) {
- fprintf(stderr,
- "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
- } else {
- fprintf(stderr,
- "InnoDB: The file relay-log.info was successfully overwritten.\n");
- }
- } else {
- fprintf(stderr,
- "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
- }
+ innobase_do_overwrite_relay_log_info();
}
-#endif /* MYSQL_SERVER */
-#endif /* HAVE_REPLICATION */
innobase_old_blocks_pct = buf_LRU_old_ratio_update(
innobase_old_blocks_pct, TRUE);
@@ -3170,6 +3235,32 @@ innobase_alter_table_flags(
| HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE);
}
+/****************************************************************//**
+Copy the current replication position from MySQL to a transaction. */
+static
+void
+innobase_copy_repl_coords_to_trx(
+/*=============================*/
+ const THD* thd, /*!< in: thread handle */
+ trx_t* trx) /*!< in/out: transaction */
+{
+ if (thd && thd_is_replication_slave_thread(thd)) {
+ /* Update the replication position info inside InnoDB.
+ In embedded server, does nothing. */
+ const char *log_file_name, *group_relay_log_name;
+ ulonglong log_pos, relay_log_pos;
+ bool res = rpl_get_position_info(&log_file_name, &log_pos,
+ &group_relay_log_name,
+ &relay_log_pos);
+ if (res) {
+ trx->mysql_master_log_file_name = log_file_name;
+ trx->mysql_master_log_pos = (ib_int64_t)log_pos;
+ trx->mysql_relay_log_file_name = group_relay_log_name;
+ trx->mysql_relay_log_pos = (ib_int64_t)relay_log_pos;
+ }
+ }
+}
+
/*****************************************************************//**
Commits a transaction in an InnoDB database. */
static
@@ -3179,27 +3270,12 @@ innobase_commit_low(
trx_t* trx) /*!< in: transaction handle */
{
if (trx_is_started(trx)) {
-#ifdef HAVE_REPLICATION
-#ifdef MYSQL_SERVER
- THD *thd=current_thd;
-
- if (thd && thd_is_replication_slave_thread(thd)) {
- /* Update the replication position info inside InnoDB.
- In embedded server, does nothing. */
- const char *log_file_name, *group_relay_log_name;
- ulonglong log_pos, relay_log_pos;
- bool res = rpl_get_position_info(&log_file_name, &log_pos,
- &group_relay_log_name,
- &relay_log_pos);
- if (res) {
- trx->mysql_master_log_file_name = log_file_name;
- trx->mysql_master_log_pos = (ib_int64_t)log_pos;
- trx->mysql_relay_log_file_name = group_relay_log_name;
- trx->mysql_relay_log_pos = (ib_int64_t)relay_log_pos;
- }
- }
-#endif /* MYSQL_SERVER */
-#endif /* HAVE_REPLICATION */
+
+ /* Save the current replication position for write to trx sys
+ header for undo purposes, see the comment at corresponding call
+ at innobase_xa_prepare(). */
+
+ innobase_copy_repl_coords_to_trx(current_thd, trx);
trx_commit_for_mysql(trx);
}
@@ -3399,6 +3475,9 @@ innobase_commit(
if (all
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
+ DBUG_EXECUTE_IF("crash_innodb_before_commit",
+ DBUG_SUICIDE(););
+
/* Run the fast part of commit if we did not already. */
if (!trx_is_active_commit_ordered(trx)) {
innobase_commit_ordered_2(trx, thd);
@@ -11559,7 +11638,27 @@ innobase_xa_prepare(
ut_ad(trx_is_registered_for_2pc(trx));
+ /* Update the replication position info in current trx. This
+ is different from the binlog position update that happens
+ during XA COMMIT. In contrast to that, the slave position is
+ an actual part of the changes made by this transaction and thus
+ must be updated in the XA PREPARE stage. Since the trx sys
+ header page changes are not undo-logged, again store this
+ position in a different field in the XA COMMIT stage, so that
+ it might be used in case of rollbacks. */
+
+ /* Since currently there might be only one slave SQL thread, we
+ don't need to take any precautions (e.g. prepare_commit_mutex)
+ to ensure position ordering. Revisit this in 5.6 which has
+ both the multi-threaded replication to cause us problems and
+ the group commit to solve them. */
+
+ innobase_copy_repl_coords_to_trx(thd, trx);
+
error = (int) trx_prepare_for_mysql(trx);
+
+ DBUG_EXECUTE_IF("crash_innodb_after_prepare",
+ DBUG_SUICIDE(););
} else {
/* We just mark the SQL statement ended and do not do a
transaction prepare */
@@ -11652,6 +11751,22 @@ innobase_rollback_by_xid(
if (trx) {
int ret = innobase_rollback_trx(trx);
trx_free_for_background(trx);
+
+ if (innobase_overwrite_relay_log_info) {
+
+ /* On rollback of a prepared transaction revert the
+ current slave positions to the ones recorded by the
+ last COMMITTed transaction. This has an effect of
+ undoing the position change caused by the transaction
+ being rolled back. Assumes single-threaded slave SQL
+ thread. If the server has non-master write traffic
+ with XA rollbacks, this will cause additional spurious
+ slave info log overwrites, which should be harmless. */
+
+ trx_sys_print_committed_mysql_master_log_pos();
+ innobase_do_overwrite_relay_log_info();
+ }
+
return(ret);
} else {
return(XAER_NOTA);
@@ -12670,6 +12785,12 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
+static MYSQL_SYSVAR_BOOL(buffer_pool_populate, srv_buf_pool_populate,
+ PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
+ "Preallocate (pre-fault) the page frames required for the mapping "
+ "established by the buffer pool memory region. Disabled by default.",
+ NULL, NULL, FALSE);
+
static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Number of buffer pool instances, set to higher value on high-end machines to increase scalability",
@@ -13049,6 +13170,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(additional_mem_pool_size),
MYSQL_SYSVAR(autoextend_increment),
MYSQL_SYSVAR(buffer_pool_size),
+ MYSQL_SYSVAR(buffer_pool_populate),
MYSQL_SYSVAR(buffer_pool_instances),
MYSQL_SYSVAR(buffer_pool_shm_key),
MYSQL_SYSVAR(buffer_pool_shm_checksum),
@@ -13194,7 +13316,10 @@ i_s_innodb_buffer_pool_pages,
i_s_innodb_buffer_pool_pages_index,
i_s_innodb_buffer_pool_pages_blob,
i_s_innodb_admin_command,
-i_s_innodb_changed_pages
+i_s_innodb_changed_pages,
+i_s_innodb_buffer_page,
+i_s_innodb_buffer_page_lru,
+i_s_innodb_buffer_stats
maria_declare_plugin_end;
/** @brief Initialize the default value of innodb_commit_concurrency.
diff --git a/storage/xtradb/handler/i_s.cc b/storage/xtradb/handler/i_s.cc
index 57a091ea80d..29a80594344 100644
--- a/storage/xtradb/handler/i_s.cc
+++ b/storage/xtradb/handler/i_s.cc
@@ -64,8 +64,93 @@ extern "C" {
#include "buf0lru.h" /* for XTRA_LRU_[DUMP/RESTORE] */
#include "btr0btr.h" /* for btr_page_get_index_id */
#include "log0online.h"
+#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;
+ /*!< Number of records on Page */
+ unsigned data_size;
+ /*!< 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); \
@@ -1570,7 +1655,6 @@ i_s_cmpmem_fill_low(
buf_pool = buf_pool_from_array(i);
- //buf_pool_mutex_enter(buf_pool);
mutex_enter(&buf_pool->zip_free_mutex);
for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
@@ -1601,7 +1685,6 @@ i_s_cmpmem_fill_low(
}
}
- //buf_pool_mutex_exit(buf_pool);
mutex_exit(&buf_pool->zip_free_mutex);
if (status) {
@@ -1771,6 +1854,1755 @@ UNIV_INTERN struct st_maria_plugin i_s_innodb_cmpmem_reset =
INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
};
+/* 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_maria_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),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
+/* 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;
+ mutex_t* block_mutex;
+
+ /* 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);
+
+ /* GO through each block in the chunk */
+ for (n_blocks = num_to_process; n_blocks--; block++) {
+ block_mutex = buf_page_get_mutex_enter(&block->page);
+ i_s_innodb_buffer_page_get_info(
+ &block->page, pool_id, block_id,
+ info_buffer + num_page);
+ mutex_exit(block_mutex);
+ block_id++;
+ num_page++;
+ }
+
+
+ /* 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_maria_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),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
+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;
+ mutex_t* block_mutex;
+
+ DBUG_ENTER("i_s_innodb_fill_buffer_lru");
+
+ RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
+
+ /* Obtain buf_pool mutex before allocate info_buffer, since
+ UT_LIST_GET_LEN(buf_pool->LRU) could change */
+ mutex_enter(&buf_pool->LRU_list_mutex);
+
+ 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) {
+ block_mutex = buf_page_get_mutex_enter(bpage);
+ /* 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);
+ mutex_exit(block_mutex);
+
+ lru_pos++;
+ }
+
+ ut_ad(lru_pos == lru_len);
+ ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
+
+exit:
+ mutex_exit(&buf_pool->LRU_list_mutex);
+
+ 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_maria_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),
+
+ INNODB_VERSION_STR, MariaDB_PLUGIN_MATURITY_STABLE
+};
+
/*******************************************************************//**
Unbind a dynamic INFORMATION_SCHEMA table.
@return 0 on success */
diff --git a/storage/xtradb/handler/i_s.h b/storage/xtradb/handler/i_s.h
index a8964356747..620309bebfe 100644
--- a/storage/xtradb/handler/i_s.h
+++ b/storage/xtradb/handler/i_s.h
@@ -52,5 +52,8 @@ extern struct st_maria_plugin i_s_innodb_buffer_pool_pages;
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index;
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob;
extern struct st_maria_plugin i_s_innodb_changed_pages;
+extern struct st_maria_plugin i_s_innodb_buffer_page;
+extern struct st_maria_plugin i_s_innodb_buffer_page_lru;
+extern struct st_maria_plugin i_s_innodb_buffer_stats;
#endif /* i_s_h */
diff --git a/storage/xtradb/ibuf/ibuf0ibuf.c b/storage/xtradb/ibuf/ibuf0ibuf.c
index 562f207268a..78cb6e20176 100644
--- a/storage/xtradb/ibuf/ibuf0ibuf.c
+++ b/storage/xtradb/ibuf/ibuf0ibuf.c
@@ -3650,11 +3650,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/xtradb/include/buf0buf.h b/storage/xtradb/include/buf0buf.h
index 1a4990be69f..d48c7f0212f 100644
--- a/storage/xtradb/include/buf0buf.h
+++ b/storage/xtradb/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
@@ -233,6 +236,7 @@ ulint
buf_pool_init(
/*=========*/
ulint size, /*!< in: Size of the total pool in bytes */
+ ibool populate, /*!< in: Force virtual page preallocation */
ulint n_instances); /*!< in: Number of instances */
/********************************************************************//**
Frees the buffer pool at shutdown. This must not be invoked before
@@ -778,6 +782,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.
@@ -1364,12 +1380,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
@@ -1384,7 +1413,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/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic
index 6595e86a8fe..221f86d9d62 100644
--- a/storage/xtradb/include/buf0buf.ic
+++ b/storage/xtradb/include/buf0buf.ic
@@ -36,6 +36,8 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0lru.h"
#include "buf0rea.h"
#include "srv0srv.h"
+#include "buf0types.h"
+
/*********************************************************************//**
Gets the current size of buffer buf_pool in bytes.
@return size in bytes */
@@ -1354,4 +1356,21 @@ buf_pool_page_hash_x_unlock_all(void)
rw_lock_x_unlock(&buf_pool->page_hash_latch);
}
}
+/*********************************************************************//**
+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/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index 19bf5960ae4..7da62e68e56 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -144,6 +144,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/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index 2907365a32a..51e331c3b5d 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -111,7 +111,7 @@ UNIV_INTERN
ibool
thd_is_replication_slave_thread(
/*============================*/
- void* thd); /*!< in: thread handle (THD*) */
+ const void* thd); /*!< in: thread handle (THD*) */
/******************************************************************//**
Returns true if the transaction this thread is processing has edited
diff --git a/storage/xtradb/include/log0log.h b/storage/xtradb/include/log0log.h
index 96c4b81695a..9a149bcfa76 100644
--- a/storage/xtradb/include/log0log.h
+++ b/storage/xtradb/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/xtradb/include/os0proc.h b/storage/xtradb/include/os0proc.h
index fd46bd7db87..a78b1c2a250 100644
--- a/storage/xtradb/include/os0proc.h
+++ b/storage/xtradb/include/os0proc.h
@@ -58,7 +58,8 @@ UNIV_INTERN
void*
os_mem_alloc_large(
/*===============*/
- ulint* n); /*!< in/out: number of bytes */
+ ulint* n, /*!< in/out: number of bytes */
+ ibool populate); /*!< in: virtual page preallocation */
/****************************************************************//**
Frees large pages memory. */
UNIV_INTERN
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index b8820f1b7c9..a95eb8a1d58 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -182,6 +182,7 @@ extern my_bool srv_use_sys_malloc;
extern ibool srv_use_sys_malloc;
#endif /* UNIV_HOTBACKUP */
extern ulint srv_buf_pool_size; /*!< requested size in bytes */
+extern my_bool srv_buf_pool_populate; /*!< virtual page preallocation */
extern ulint srv_buf_pool_instances; /*!< requested number of buffer pool instances */
extern ulint srv_buf_pool_old_size; /*!< previously requested size */
extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h
index c933fb405e1..cba21ae97a9 100644
--- a/storage/xtradb/include/trx0sys.h
+++ b/storage/xtradb/include/trx0sys.h
@@ -342,6 +342,14 @@ void
trx_sys_print_mysql_binlog_offset(void);
/*===================================*/
/*****************************************************************//**
+Prints to stderr the MySQL master log offset info in the trx system header
+COMMIT set of fields if the magic number shows it valid and stores it
+in global variables. */
+UNIV_INTERN
+void
+trx_sys_print_committed_mysql_master_log_pos(void);
+/*==============================================*/
+/*****************************************************************//**
Prints to stderr the MySQL master log offset info in the trx system header if
the magic number shows it valid. */
UNIV_INTERN
@@ -534,10 +542,16 @@ We must remember this limit in order to keep file compatibility. */
//# error "UNIV_PAGE_SIZE < 4096"
//#endif
/** The offset of the MySQL replication info in the trx system header;
-this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
+this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below. These are
+written at prepare time and are the main copy. */
#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
+/** The copy of the above which is made at transaction COMMIT time. If binlog
+crash recovery rollbacks a PREPAREd transaction, they are copied back. */
+#define TRX_SYS_COMMIT_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 3000)
+#define TRX_SYS_COMMIT_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 2500)
+
/** The offset of the MySQL binlog offset info in the trx system header */
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /*!< magic number which is
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index 9aee2a0c7f9..5d2cd2d0313 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_BUGFIX 8
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 29.0
+#define PERCONA_INNODB_VERSION 29.1
#endif
/* The following is the InnoDB version as shown in
diff --git a/storage/xtradb/os/os0proc.c b/storage/xtradb/os/os0proc.c
index 68321e1aaf9..c9ee707e923 100644
--- a/storage/xtradb/os/os0proc.c
+++ b/storage/xtradb/os/os0proc.c
@@ -32,6 +32,12 @@ Created 9/30/1995 Heikki Tuuri
#include "ut0mem.h"
#include "ut0byte.h"
+/* Linux release version */
+#if defined(UNIV_LINUX) && defined(_GNU_SOURCE)
+#include <string.h> /* strverscmp() */
+#include <sys/utsname.h> /* uname() */
+#endif
+
/* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
MAP_ANON but MAP_ANON is marked as deprecated */
#if defined(MAP_ANONYMOUS)
@@ -40,6 +46,13 @@ MAP_ANON but MAP_ANON is marked as deprecated */
#define OS_MAP_ANON MAP_ANON
#endif
+/* Linux's MAP_POPULATE */
+#if defined(MAP_POPULATE)
+#define OS_MAP_POPULATE MAP_POPULATE
+#else
+#define OS_MAP_POPULATE 0
+#endif
+
UNIV_INTERN ibool os_use_large_pages;
/* Large page size. This may be a boot-time option on some platforms */
UNIV_INTERN ulint os_large_page_size;
@@ -63,13 +76,32 @@ os_proc_get_number(void)
}
/****************************************************************//**
+Retrieve and compare operating system release.
+@return TRUE if the OS release is equal to, or later than release. */
+UNIV_INTERN
+ibool
+os_compare_release(
+/*===============*/
+ const char* release /*!< in: OS release */
+ __attribute__((unused)))
+{
+#if defined(UNIV_LINUX) && defined(_GNU_SOURCE)
+ struct utsname name;
+ return uname(&name) == 0 && strverscmp(name.release, release) >= 0;
+#else
+ return 0;
+#endif
+}
+
+/****************************************************************//**
Allocates large pages memory.
@return allocated memory */
UNIV_INTERN
void*
os_mem_alloc_large(
/*===============*/
- ulint* n) /*!< in/out: number of bytes */
+ ulint* n, /*!< in/out: number of bytes */
+ ibool populate) /*!< in: virtual page preallocation */
{
void* ptr;
ulint size;
@@ -155,12 +187,13 @@ skip:
ut_ad(ut_is_2pow(size));
size = *n = ut_2pow_round(*n + (size - 1), size);
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | OS_MAP_ANON, -1, 0);
+ MAP_PRIVATE | OS_MAP_ANON |
+ (populate ? OS_MAP_POPULATE : 0), -1, 0);
if (UNIV_UNLIKELY(ptr == (void*) -1)) {
fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
" errno %lu\n",
(ulong) size, (ulong) errno);
- ptr = NULL;
+ return(NULL);
} else {
os_fast_mutex_lock(&ut_list_mutex);
ut_total_allocated_memory += size;
@@ -168,6 +201,25 @@ skip:
UNIV_MEM_ALLOC(ptr, size);
}
#endif
+
+#if OS_MAP_ANON && OS_MAP_POPULATE
+ /* MAP_POPULATE is only supported for private mappings
+ since Linux 2.6.23. */
+ populate = populate && !os_compare_release("2.6.23");
+
+ if (populate) {
+ fprintf(stderr, "InnoDB: Warning: mmap(MAP_POPULATE) "
+ "is not supported for private mappings. "
+ "Forcing preallocation by faulting in pages.\n");
+ }
+#endif
+
+ /* Initialize the entire buffer to force the allocation
+ of physical memory page frames. */
+ if (populate) {
+ memset(ptr, '\0', size);
+ }
+
return(ptr);
}
diff --git a/storage/xtradb/page/page0page.c b/storage/xtradb/page/page0page.c
index 4a389bbe5b8..e29fa2eb1e5 100644
--- a/storage/xtradb/page/page0page.c
+++ b/storage/xtradb/page/page0page.c
@@ -781,12 +781,18 @@ 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
@@ -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);
}
}
diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c
index b21d48c7552..3ae4c227ddc 100644
--- a/storage/xtradb/row/row0ins.c
+++ b/storage/xtradb/row/row0ins.c
@@ -2181,9 +2181,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/xtradb/row/row0merge.c b/storage/xtradb/row/row0merge.c
index c7d6304d6a7..0fd13f5339c 100644
--- a/storage/xtradb/row/row0merge.c
+++ b/storage/xtradb/row/row0merge.c
@@ -1254,11 +1254,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);
}
@@ -2720,7 +2734,7 @@ row_merge_build_indexes(
merge_files = mem_alloc(n_indexes * sizeof *merge_files);
block_size = 3 * merge_sort_block_size;
- block_mem = os_mem_alloc_large(&block_size);
+ block_mem = os_mem_alloc_large(&block_size, FALSE);
for (i = 0; i < UT_ARR_SIZE(block); i++) {
block[i] = (row_merge_block_t ) ((byte *) block_mem +
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c
index dff9fc07a7f..9d479ac6c87 100644
--- a/storage/xtradb/srv/srv0srv.c
+++ b/storage/xtradb/srv/srv0srv.c
@@ -232,6 +232,8 @@ UNIV_INTERN const byte* srv_latin1_ordering;
UNIV_INTERN my_bool srv_use_sys_malloc = TRUE;
/* requested size in kilobytes */
UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
+/* force virtual page preallocation (prefault) */
+UNIV_INTERN my_bool srv_buf_pool_populate = FALSE;
/* requested number of buffer pool instances */
UNIV_INTERN ulint srv_buf_pool_instances = 1;
/* previously requested size */
diff --git a/storage/xtradb/srv/srv0start.c b/storage/xtradb/srv/srv0start.c
index 7c98f74909e..65a775b56da 100644
--- a/storage/xtradb/srv/srv0start.c
+++ b/storage/xtradb/srv/srv0start.c
@@ -1543,7 +1543,8 @@ innobase_start_or_create_for_mysql(void)
((double) srv_buf_pool_size) / (1024 * 1024));
}
- err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
+ err = buf_pool_init(srv_buf_pool_size, (ibool) srv_buf_pool_populate,
+ srv_buf_pool_instances);
ut_print_timestamp(stderr);
fprintf(stderr,
diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c
index 7d303c2563c..c40bf02a7a2 100644
--- a/storage/xtradb/trx/trx0sys.c
+++ b/storage/xtradb/trx/trx0sys.c
@@ -959,8 +959,31 @@ trx_sys_print_mysql_binlog_offset(void)
}
/*****************************************************************//**
-Prints to stderr the MySQL master log offset info in the trx system header if
-the magic number shows it valid. */
+Reads the log coordinates at the given offset in the trx sys header. */
+static
+void
+trx_sys_read_log_pos(
+/*=================*/
+ const trx_sysf_t* sys_header, /*!< in: the trx sys header */
+ uint header_offset, /*!< in: coord offset in the
+ header */
+ char* log_fn, /*!< out: the log file name */
+ ib_int64_t* log_pos) /*!< out: the log poistion */
+{
+ ut_memcpy(log_fn, sys_header + header_offset + TRX_SYS_MYSQL_LOG_NAME,
+ TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+
+ *log_pos =
+ (((ib_int64_t)mach_read_from_4(sys_header + header_offset
+ + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
+ + mach_read_from_4(sys_header + header_offset
+ + TRX_SYS_MYSQL_LOG_OFFSET_LOW);
+}
+
+/*****************************************************************//**
+Prints to stderr the MySQL master log offset info in the trx system header
+PREPARE set of fields if the magic number shows it valid and stores it
+in global variables. */
UNIV_INTERN
void
trx_sys_print_mysql_master_log_pos(void)
@@ -982,60 +1005,79 @@ trx_sys_print_mysql_master_log_pos(void)
return;
}
+ /* Copy the master log position info to global variables we can
+ use in ha_innobase.cc to initialize glob_mi to right values */
+ trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_MASTER_LOG_INFO,
+ trx_sys_mysql_master_log_name,
+ &trx_sys_mysql_master_log_pos);
+
+ trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_RELAY_LOG_INFO,
+ trx_sys_mysql_relay_log_name,
+ &trx_sys_mysql_relay_log_pos);
+
+ mtr_commit(&mtr);
+
fprintf(stderr,
"InnoDB: In a MySQL replication slave the last"
" master binlog file\n"
- "InnoDB: position %lu %lu, file name %s\n",
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME);
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_master_log_pos,
+ trx_sys_mysql_master_log_name);
fprintf(stderr,
"InnoDB: and relay log file\n"
- "InnoDB: position %lu %lu, file name %s\n",
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
- (ulong) mach_read_from_4(sys_header
- + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME);
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_relay_log_pos,
+ trx_sys_mysql_relay_log_name);
+}
- /* Copy the master log position info to global variables we can
- use in ha_innobase.cc to initialize glob_mi to right values */
+/*****************************************************************//**
+Prints to stderr the MySQL master log offset info in the trx system header
+COMMIT set of fields if the magic number shows it valid and stores it
+in global variables. */
+UNIV_INTERN
+void
+trx_sys_print_committed_mysql_master_log_pos(void)
+/*==============================================*/
+{
+ trx_sysf_t* sys_header;
+ mtr_t mtr;
- ut_memcpy(trx_sys_mysql_master_log_name,
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME,
- TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ mtr_start(&mtr);
- trx_sys_mysql_master_log_pos
- = (((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
- + ((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
-
- ut_memcpy(trx_sys_mysql_relay_log_name,
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_NAME,
- TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
+ sys_header = trx_sysf_get(&mtr);
+
+ if (mach_read_from_4(sys_header + TRX_SYS_COMMIT_MASTER_LOG_INFO
+ + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
+ != TRX_SYS_MYSQL_LOG_MAGIC_N) {
+
+ mtr_commit(&mtr);
+
+ return;
+ }
+
+ /* Copy the master log position info to global variables we can
+ use in ha_innobase.cc to initialize glob_mi to right values */
+ trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_MASTER_LOG_INFO,
+ trx_sys_mysql_master_log_name,
+ &trx_sys_mysql_master_log_pos);
+
+ trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_RELAY_LOG_INFO,
+ trx_sys_mysql_relay_log_name,
+ &trx_sys_mysql_relay_log_pos);
- trx_sys_mysql_relay_log_pos
- = (((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
- + ((ib_int64_t) mach_read_from_4(
- sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
mtr_commit(&mtr);
+
+ fprintf(stderr,
+ "InnoDB: In a MySQL replication slave the last"
+ " master binlog file\n"
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_master_log_pos, trx_sys_mysql_master_log_name);
+
+ fprintf(stderr,
+ "InnoDB: and relay log file\n"
+ "InnoDB: position %llu, file name %s\n",
+ trx_sys_mysql_relay_log_pos, trx_sys_mysql_relay_log_name);
}
/****************************************************************//**
diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c
index c9fccaad16b..eea8e861387 100644
--- a/storage/xtradb/trx/trx0trx.c
+++ b/storage/xtradb/trx/trx0trx.c
@@ -938,13 +938,13 @@ trx_write_serialisation_history(
sys_header,
trx->mysql_relay_log_file_name,
trx->mysql_relay_log_pos,
- TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
+ TRX_SYS_COMMIT_RELAY_LOG_INFO, &mtr);
trx_sys_update_mysql_binlog_offset(
sys_header,
trx->mysql_master_log_file_name,
trx->mysql_master_log_pos,
- TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
+ TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr);
trx->mysql_master_log_file_name = "";
}
@@ -2050,6 +2050,23 @@ trx_prepare_off_kernel(
mutex_exit(&(rseg->mutex));
+ if (trx->mysql_master_log_file_name[0] != '\0') {
+ /* This database server is a MySQL replication slave */
+ trx_sysf_t* sys_header = trx_sysf_get(&mtr);
+
+ trx_sys_update_mysql_binlog_offset(
+ sys_header,
+ trx->mysql_relay_log_file_name,
+ trx->mysql_relay_log_pos,
+ TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
+ trx_sys_update_mysql_binlog_offset(
+ sys_header,
+ trx->mysql_master_log_file_name,
+ trx->mysql_master_log_pos,
+ TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
+ trx->mysql_master_log_file_name = "";
+ }
+
/*--------------*/
mtr_commit(&mtr); /* This mtr commit makes the
transaction prepared in the file-based