1 /*****************************************************************************
2 
3 Copyright (c) 2007, 2013, Innobase Oy. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************//**
20 @file handler/i_s.cc
21 InnoDB INFORMATION SCHEMA tables interface to MySQL.
22 
23 Created July 18, 2007 Vasil Dimov
24 *******************************************************/
25 
26 #include <mysqld_error.h>
27 #include <sql_acl.h>
28 
29 #include <m_ctype.h>
30 #include <hash.h>
31 #include <myisampack.h>
32 #include <mysys_err.h>
33 #include <my_sys.h>
34 #include "i_s.h"
35 #include <sql_plugin.h>
36 #include <mysql/innodb_priv.h>
37 
38 extern "C" {
39 #include "btr0types.h"
40 #include "buf0buddy.h"
41 #include "buf0buf.h"
42 #include "ibuf0ibuf.h"
43 #include "dict0mem.h"
44 #include "dict0types.h"
45 #include "dict0boot.h"
46 #include "ha_prototypes.h"
47 #include "srv0start.h"
48 #include "trx0i_s.h"
49 #include "trx0trx.h"
50 #include "btr0btr.h"
51 #include "page0zip.h"
52 #include "log0log.h"
53 }
54 
55 /** structure associates a name string with a file page type and/or buffer
56 page state. */
57 struct buffer_page_desc_str_struct{
58 	const char*	type_str;	/*!< String explain the page
59 					type/state */
60 	ulint		type_value;	/*!< Page type or page state */
61 };
62 
63 typedef struct buffer_page_desc_str_struct	buf_page_desc_str_t;
64 
65 /** Change buffer B-tree page */
66 #define	I_S_PAGE_TYPE_IBUF		(FIL_PAGE_TYPE_LAST + 1)
67 
68 /** Any states greater than I_S_PAGE_TYPE_IBUF would be treated as
69 unknown. */
70 #define	I_S_PAGE_TYPE_UNKNOWN		(I_S_PAGE_TYPE_IBUF + 1)
71 
72 /** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position
73 in i_s_page_type[] array */
74 #define I_S_PAGE_TYPE_INDEX		1
75 
76 /** Name string for File Page Types */
77 static buf_page_desc_str_t	i_s_page_type[] = {
78 	{"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED},
79 	{"INDEX", FIL_PAGE_INDEX},
80 	{"UNDO_LOG", FIL_PAGE_UNDO_LOG},
81 	{"INODE", FIL_PAGE_INODE},
82 	{"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST},
83 	{"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP},
84 	{"SYSTEM", FIL_PAGE_TYPE_SYS},
85 	{"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS},
86 	{"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR},
87 	{"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES},
88 	{"BLOB", FIL_PAGE_TYPE_BLOB},
89 	{"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB},
90 	{"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2},
91 	{"IBUF_INDEX", I_S_PAGE_TYPE_IBUF},
92 	{"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN}
93 };
94 
95 /* Check if we can hold all page type in a 4 bit value */
96 #if I_S_PAGE_TYPE_UNKNOWN > 1<<4
97 # error "i_s_page_type[] is too large"
98 #endif
99 
100 /** This structure defines information we will fetch from pages
101 currently cached in the buffer pool. It will be used to populate
102 table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */
103 struct buffer_page_info_struct{
104 	ulint		block_id;	/*!< Buffer Pool block ID */
105 	unsigned	space_id:32;	/*!< Tablespace ID */
106 	unsigned	page_num:32;	/*!< Page number/offset */
107 	unsigned	access_time:32;	/*!< Time of first access */
108 	unsigned	pool_id:MAX_BUFFER_POOLS_BITS;
109 					/*!< Buffer Pool ID. Must be less than
110 					MAX_BUFFER_POOLS */
111 	unsigned	flush_type:2;	/*!< Flush type */
112 	unsigned	io_fix:2;	/*!< type of pending I/O operation */
113 	unsigned	fix_count:19;	/*!< Count of how manyfold this block
114 					is bufferfixed */
115 	unsigned	hashed:1;	/*!< Whether hash index has been
116 					built on this page */
117 	unsigned	is_old:1;	/*!< TRUE if the block is in the old
118 					blocks in buf_pool->LRU_old */
119 	unsigned	freed_page_clock:31; /*!< the value of
120 					buf_pool->freed_page_clock */
121 	unsigned	zip_ssize:PAGE_ZIP_SSIZE_BITS;
122 					/*!< Compressed page size */
123 	unsigned	page_state:BUF_PAGE_STATE_BITS; /*!< Page state */
124 	unsigned	page_type:4;	/*!< Page type */
125 	unsigned	num_recs:UNIV_PAGE_SIZE_SHIFT-2;
126 					/*!< Number of records on Page */
127 	unsigned	data_size:UNIV_PAGE_SIZE_SHIFT;
128 					/*!< Sum of the sizes of the records */
129 	lsn_t		newest_mod;	/*!< Log sequence number of
130 					the youngest modification */
131 	lsn_t		oldest_mod;	/*!< Log sequence number of
132 					the oldest modification */
133 	index_id_t	index_id;	/*!< Index ID if a index page */
134 };
135 
136 typedef struct buffer_page_info_struct	buf_page_info_t;
137 
138 /** maximum number of buffer page info we would cache. */
139 #define MAX_BUF_INFO_CACHED		10000
140 
141 
142 #define OK(expr)		\
143 	if ((expr) != 0) {	\
144 		DBUG_RETURN(1);	\
145 	}
146 
147 #define RETURN_IF_INNODB_NOT_STARTED(plugin_name)			\
148 do {									\
149 	if (!srv_was_started) {						\
150 		push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,	\
151 				    ER_CANT_FIND_SYSTEM_REC,		\
152 				    "InnoDB: SELECTing from "		\
153 				    "INFORMATION_SCHEMA.%s but "	\
154 				    "the InnoDB storage engine "	\
155 				    "is not installed", plugin_name);	\
156 		DBUG_RETURN(0);						\
157 	}								\
158 } while (0)
159 
160 #if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && !defined __INTEL_COMPILER
161 #define STRUCT_FLD(name, value)	name: value
162 #else
163 #define STRUCT_FLD(name, value)	value
164 #endif
165 
166 /* Don't use a static const variable here, as some C++ compilers (notably
167 HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
168 #define END_OF_ST_FIELD_INFO \
169 	{STRUCT_FLD(field_name,		NULL), \
170 	 STRUCT_FLD(field_length,	0), \
171 	 STRUCT_FLD(field_type,		MYSQL_TYPE_NULL), \
172 	 STRUCT_FLD(value,		0), \
173 	 STRUCT_FLD(field_flags,	0), \
174 	 STRUCT_FLD(old_name,		""), \
175 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)}
176 
177 /*
178 Use the following types mapping:
179 
180 C type	ST_FIELD_INFO::field_type
181 ---------------------------------
182 long			MYSQL_TYPE_LONGLONG
183 (field_length=MY_INT64_NUM_DECIMAL_DIGITS)
184 
185 long unsigned		MYSQL_TYPE_LONGLONG
186 (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
187 
188 char*			MYSQL_TYPE_STRING
189 (field_length=n)
190 
191 float			MYSQL_TYPE_FLOAT
192 (field_length=0 is ignored)
193 
194 void*			MYSQL_TYPE_LONGLONG
195 (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
196 
197 boolean (if else)	MYSQL_TYPE_LONG
198 (field_length=1)
199 
200 time_t			MYSQL_TYPE_DATETIME
201 (field_length=0 ignored)
202 ---------------------------------
203 */
204 
205 /*******************************************************************//**
206 Common function to fill any of the dynamic tables:
207 INFORMATION_SCHEMA.innodb_trx
208 INFORMATION_SCHEMA.innodb_locks
209 INFORMATION_SCHEMA.innodb_lock_waits
210 @return	0 on success */
211 static
212 int
213 trx_i_s_common_fill_table(
214 /*======================*/
215 	THD*		thd,	/*!< in: thread */
216 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
217 	COND*		cond);	/*!< in: condition (not used) */
218 
219 /*******************************************************************//**
220 Unbind a dynamic INFORMATION_SCHEMA table.
221 @return	0 on success */
222 static
223 int
224 i_s_common_deinit(
225 /*==============*/
226 	void*	p);	/*!< in/out: table schema object */
227 /*******************************************************************//**
228 Auxiliary function to store time_t value in MYSQL_TYPE_DATETIME
229 field.
230 @return	0 on success */
231 static
232 int
field_store_time_t(Field * field,time_t time)233 field_store_time_t(
234 /*===============*/
235 	Field*	field,	/*!< in/out: target field for storage */
236 	time_t	time)	/*!< in: value to store */
237 {
238 	MYSQL_TIME	my_time;
239 	struct tm	tm_time;
240 
241 #if 0
242 	/* use this if you are sure that `variables' and `time_zone'
243 	are always initialized */
244 	thd->variables.time_zone->gmt_sec_to_TIME(
245 		&my_time, (my_time_t) time);
246 #else
247 	localtime_r(&time, &tm_time);
248 	localtime_to_TIME(&my_time, &tm_time);
249 	my_time.time_type = MYSQL_TIMESTAMP_DATETIME;
250 #endif
251 
252 	return(field->store_time(&my_time, MYSQL_TIMESTAMP_DATETIME));
253 }
254 
255 /*******************************************************************//**
256 Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
257 @return	0 on success */
258 static
259 int
field_store_string(Field * field,const char * str)260 field_store_string(
261 /*===============*/
262 	Field*		field,	/*!< in/out: target field for storage */
263 	const char*	str)	/*!< in: NUL-terminated utf-8 string,
264 				or NULL */
265 {
266 	int	ret;
267 
268 	if (str != NULL) {
269 
270 		ret = field->store(str, strlen(str),
271 				   system_charset_info);
272 		field->set_notnull();
273 	} else {
274 
275 		ret = 0; /* success */
276 		field->set_null();
277 	}
278 
279 	return(ret);
280 }
281 
282 /*******************************************************************//**
283 Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
284 If the value is ULINT_UNDEFINED then the field it set to NULL.
285 @return	0 on success */
286 static
287 int
field_store_ulint(Field * field,ulint n)288 field_store_ulint(
289 /*==============*/
290 	Field*	field,	/*!< in/out: target field for storage */
291 	ulint	n)	/*!< in: value to store */
292 {
293 	int	ret;
294 
295 	if (n != ULINT_UNDEFINED) {
296 
297 		ret = field->store(n);
298 		field->set_notnull();
299 	} else {
300 
301 		ret = 0; /* success */
302 		field->set_null();
303 	}
304 
305 	return(ret);
306 }
307 
308 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
309 static ST_FIELD_INFO	innodb_trx_fields_info[] =
310 {
311 #define IDX_TRX_ID		0
312 	{STRUCT_FLD(field_name,		"trx_id"),
313 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
314 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
315 	 STRUCT_FLD(value,		0),
316 	 STRUCT_FLD(field_flags,	0),
317 	 STRUCT_FLD(old_name,		""),
318 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
319 
320 #define IDX_TRX_STATE		1
321 	{STRUCT_FLD(field_name,		"trx_state"),
322 	 STRUCT_FLD(field_length,	TRX_QUE_STATE_STR_MAX_LEN + 1),
323 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
324 	 STRUCT_FLD(value,		0),
325 	 STRUCT_FLD(field_flags,	0),
326 	 STRUCT_FLD(old_name,		""),
327 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
328 
329 #define IDX_TRX_STARTED		2
330 	{STRUCT_FLD(field_name,		"trx_started"),
331 	 STRUCT_FLD(field_length,	0),
332 	 STRUCT_FLD(field_type,		MYSQL_TYPE_DATETIME),
333 	 STRUCT_FLD(value,		0),
334 	 STRUCT_FLD(field_flags,	0),
335 	 STRUCT_FLD(old_name,		""),
336 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
337 
338 #define IDX_TRX_REQUESTED_LOCK_ID	3
339 	{STRUCT_FLD(field_name,		"trx_requested_lock_id"),
340 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
341 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
342 	 STRUCT_FLD(value,		0),
343 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
344 	 STRUCT_FLD(old_name,		""),
345 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
346 
347 #define IDX_TRX_WAIT_STARTED	4
348 	{STRUCT_FLD(field_name,		"trx_wait_started"),
349 	 STRUCT_FLD(field_length,	0),
350 	 STRUCT_FLD(field_type,		MYSQL_TYPE_DATETIME),
351 	 STRUCT_FLD(value,		0),
352 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
353 	 STRUCT_FLD(old_name,		""),
354 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
355 
356 #define IDX_TRX_WEIGHT		5
357 	{STRUCT_FLD(field_name,		"trx_weight"),
358 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
359 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
360 	 STRUCT_FLD(value,		0),
361 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
362 	 STRUCT_FLD(old_name,		""),
363 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
364 
365 #define IDX_TRX_MYSQL_THREAD_ID	6
366 	{STRUCT_FLD(field_name,		"trx_mysql_thread_id"),
367 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
368 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
369 	 STRUCT_FLD(value,		0),
370 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
371 	 STRUCT_FLD(old_name,		""),
372 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
373 
374 #define IDX_TRX_QUERY		7
375 	{STRUCT_FLD(field_name,		"trx_query"),
376 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_QUERY_MAX_LEN),
377 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
378 	 STRUCT_FLD(value,		0),
379 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
380 	 STRUCT_FLD(old_name,		""),
381 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
382 
383 #define IDX_TRX_OPERATION_STATE	8
384 	{STRUCT_FLD(field_name,		"trx_operation_state"),
385 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_OP_STATE_MAX_LEN),
386 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
387 	 STRUCT_FLD(value,		0),
388 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
389 	 STRUCT_FLD(old_name,		""),
390 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
391 
392 #define IDX_TRX_TABLES_IN_USE	9
393 	{STRUCT_FLD(field_name,		"trx_tables_in_use"),
394 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
395 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
396 	 STRUCT_FLD(value,		0),
397 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
398 	 STRUCT_FLD(old_name,		""),
399 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
400 
401 #define IDX_TRX_TABLES_LOCKED	10
402 	{STRUCT_FLD(field_name,		"trx_tables_locked"),
403 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
404 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
405 	 STRUCT_FLD(value,		0),
406 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
407 	 STRUCT_FLD(old_name,		""),
408 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
409 
410 #define IDX_TRX_LOCK_STRUCTS	11
411 	{STRUCT_FLD(field_name,		"trx_lock_structs"),
412 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
413 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
414 	 STRUCT_FLD(value,		0),
415 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
416 	 STRUCT_FLD(old_name,		""),
417 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
418 
419 #define IDX_TRX_LOCK_MEMORY_BYTES	12
420 	{STRUCT_FLD(field_name,		"trx_lock_memory_bytes"),
421 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
422 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
423 	 STRUCT_FLD(value,		0),
424 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
425 	 STRUCT_FLD(old_name,		""),
426 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
427 
428 #define IDX_TRX_ROWS_LOCKED	13
429 	{STRUCT_FLD(field_name,		"trx_rows_locked"),
430 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
431 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
432 	 STRUCT_FLD(value,		0),
433 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
434 	 STRUCT_FLD(old_name,		""),
435 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
436 
437 #define IDX_TRX_ROWS_MODIFIED		14
438 	{STRUCT_FLD(field_name,		"trx_rows_modified"),
439 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
440 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
441 	 STRUCT_FLD(value,		0),
442 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
443 	 STRUCT_FLD(old_name,		""),
444 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
445 
446 #define IDX_TRX_CONNCURRENCY_TICKETS	15
447 	{STRUCT_FLD(field_name,		"trx_concurrency_tickets"),
448 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
449 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
450 	 STRUCT_FLD(value,		0),
451 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
452 	 STRUCT_FLD(old_name,		""),
453 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
454 
455 #define IDX_TRX_ISOLATION_LEVEL	16
456 	{STRUCT_FLD(field_name,		"trx_isolation_level"),
457 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_ISOLATION_LEVEL_MAX_LEN),
458 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
459 	 STRUCT_FLD(value,		0),
460 	 STRUCT_FLD(field_flags,	0),
461 	 STRUCT_FLD(old_name,		""),
462 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
463 
464 #define IDX_TRX_UNIQUE_CHECKS	17
465 	{STRUCT_FLD(field_name,		"trx_unique_checks"),
466 	 STRUCT_FLD(field_length,	1),
467 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
468 	 STRUCT_FLD(value,		1),
469 	 STRUCT_FLD(field_flags,	0),
470 	 STRUCT_FLD(old_name,		""),
471 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
472 
473 #define IDX_TRX_FOREIGN_KEY_CHECKS	18
474 	{STRUCT_FLD(field_name,		"trx_foreign_key_checks"),
475 	 STRUCT_FLD(field_length,	1),
476 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
477 	 STRUCT_FLD(value,		1),
478 	 STRUCT_FLD(field_flags,	0),
479 	 STRUCT_FLD(old_name,		""),
480 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
481 
482 #define IDX_TRX_LAST_FOREIGN_KEY_ERROR	19
483 	{STRUCT_FLD(field_name,		"trx_last_foreign_key_error"),
484 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_FK_ERROR_MAX_LEN),
485 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
486 	 STRUCT_FLD(value,		0),
487 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
488 	 STRUCT_FLD(old_name,		""),
489 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
490 
491 #define IDX_TRX_ADAPTIVE_HASH_LATCHED	20
492 	{STRUCT_FLD(field_name,		"trx_adaptive_hash_latched"),
493 	 STRUCT_FLD(field_length,	1),
494 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
495 	 STRUCT_FLD(value,		0),
496 	 STRUCT_FLD(field_flags,	0),
497 	 STRUCT_FLD(old_name,		""),
498 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
499 
500 #define IDX_TRX_ADAPTIVE_HASH_TIMEOUT	21
501 	{STRUCT_FLD(field_name,		"trx_adaptive_hash_timeout"),
502 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
503 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
504 	 STRUCT_FLD(value,		0),
505 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
506 	 STRUCT_FLD(old_name,		""),
507 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
508 
509 	END_OF_ST_FIELD_INFO
510 };
511 
512 /*******************************************************************//**
513 Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_trx
514 table with it.
515 @return	0 on success */
516 static
517 int
fill_innodb_trx_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)518 fill_innodb_trx_from_cache(
519 /*=======================*/
520 	trx_i_s_cache_t*	cache,	/*!< in: cache to read from */
521 	THD*			thd,	/*!< in: used to call
522 					schema_table_store_record() */
523 	TABLE*			table)	/*!< in/out: fill this table */
524 {
525 	Field**	fields;
526 	ulint	rows_num;
527 	char	lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
528 	ulint	i;
529 
530 	DBUG_ENTER("fill_innodb_trx_from_cache");
531 
532 	fields = table->field;
533 
534 	rows_num = trx_i_s_cache_get_rows_used(cache,
535 					       I_S_INNODB_TRX);
536 
537 	for (i = 0; i < rows_num; i++) {
538 
539 		i_s_trx_row_t*	row;
540 		char		trx_id[TRX_ID_MAX_LEN + 1];
541 
542 		row = (i_s_trx_row_t*)
543 			trx_i_s_cache_get_nth_row(
544 				cache, I_S_INNODB_TRX, i);
545 
546 		/* trx_id */
547 		ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
548 		OK(field_store_string(fields[IDX_TRX_ID], trx_id));
549 
550 		/* trx_state */
551 		OK(field_store_string(fields[IDX_TRX_STATE],
552 				      row->trx_state));
553 
554 		/* trx_started */
555 		OK(field_store_time_t(fields[IDX_TRX_STARTED],
556 				      (time_t) row->trx_started));
557 
558 		/* trx_requested_lock_id */
559 		/* trx_wait_started */
560 		if (row->trx_wait_started != 0) {
561 
562 			OK(field_store_string(
563 				   fields[IDX_TRX_REQUESTED_LOCK_ID],
564 				   trx_i_s_create_lock_id(
565 					   row->requested_lock_row,
566 					   lock_id, sizeof(lock_id))));
567 			/* field_store_string() sets it no notnull */
568 
569 			OK(field_store_time_t(
570 				   fields[IDX_TRX_WAIT_STARTED],
571 				   (time_t) row->trx_wait_started));
572 			fields[IDX_TRX_WAIT_STARTED]->set_notnull();
573 		} else {
574 
575 			fields[IDX_TRX_REQUESTED_LOCK_ID]->set_null();
576 			fields[IDX_TRX_WAIT_STARTED]->set_null();
577 		}
578 
579 		/* trx_weight */
580 		OK(fields[IDX_TRX_WEIGHT]->store((longlong) row->trx_weight,
581 						 true));
582 
583 		/* trx_mysql_thread_id */
584 		OK(fields[IDX_TRX_MYSQL_THREAD_ID]->store(
585 			   row->trx_mysql_thread_id));
586 
587 		/* trx_query */
588 		if (row->trx_query) {
589 			/* store will do appropriate character set
590 			conversion check */
591 			fields[IDX_TRX_QUERY]->store(
592 				row->trx_query, strlen(row->trx_query),
593 				row->trx_query_cs);
594 			fields[IDX_TRX_QUERY]->set_notnull();
595 		} else {
596 			fields[IDX_TRX_QUERY]->set_null();
597 		}
598 
599 		/* trx_operation_state */
600 		OK(field_store_string(fields[IDX_TRX_OPERATION_STATE],
601 				      row->trx_operation_state));
602 
603 		/* trx_tables_in_use */
604 		OK(fields[IDX_TRX_TABLES_IN_USE]->store(
605 			   (longlong) row->trx_tables_in_use, true));
606 
607 		/* trx_tables_locked */
608 		OK(fields[IDX_TRX_TABLES_LOCKED]->store(
609 			   (longlong) row->trx_tables_locked, true));
610 
611 		/* trx_lock_structs */
612 		OK(fields[IDX_TRX_LOCK_STRUCTS]->store(
613 			   (longlong) row->trx_lock_structs, true));
614 
615 		/* trx_lock_memory_bytes */
616 		OK(fields[IDX_TRX_LOCK_MEMORY_BYTES]->store(
617 			   (longlong) row->trx_lock_memory_bytes, true));
618 
619 		/* trx_rows_locked */
620 		OK(fields[IDX_TRX_ROWS_LOCKED]->store(
621 			   (longlong) row->trx_rows_locked, true));
622 
623 		/* trx_rows_modified */
624 		OK(fields[IDX_TRX_ROWS_MODIFIED]->store(
625 			   (longlong) row->trx_rows_modified, true));
626 
627 		/* trx_concurrency_tickets */
628 		OK(fields[IDX_TRX_CONNCURRENCY_TICKETS]->store(
629 			   (longlong) row->trx_concurrency_tickets, true));
630 
631 		/* trx_isolation_level */
632 		OK(field_store_string(fields[IDX_TRX_ISOLATION_LEVEL],
633 				      row->trx_isolation_level));
634 
635 		/* trx_unique_checks */
636 		OK(fields[IDX_TRX_UNIQUE_CHECKS]->store(
637 			   row->trx_unique_checks));
638 
639 		/* trx_foreign_key_checks */
640 		OK(fields[IDX_TRX_FOREIGN_KEY_CHECKS]->store(
641 			   row->trx_foreign_key_checks));
642 
643 		/* trx_last_foreign_key_error */
644 		OK(field_store_string(fields[IDX_TRX_LAST_FOREIGN_KEY_ERROR],
645 				      row->trx_foreign_key_error));
646 
647 		/* trx_adaptive_hash_latched */
648 		OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store(
649 			   row->trx_has_search_latch));
650 
651 		/* trx_adaptive_hash_timeout */
652 		OK(fields[IDX_TRX_ADAPTIVE_HASH_TIMEOUT]->store(
653 			   (longlong) row->trx_search_latch_timeout, true));
654 
655 		OK(schema_table_store_record(thd, table));
656 	}
657 
658 	DBUG_RETURN(0);
659 }
660 
661 /*******************************************************************//**
662 Bind the dynamic table INFORMATION_SCHEMA.innodb_trx
663 @return	0 on success */
664 static
665 int
innodb_trx_init(void * p)666 innodb_trx_init(
667 /*============*/
668 	void*	p)	/*!< in/out: table schema object */
669 {
670 	ST_SCHEMA_TABLE*	schema;
671 
672 	DBUG_ENTER("innodb_trx_init");
673 
674 	schema = (ST_SCHEMA_TABLE*) p;
675 
676 	schema->fields_info = innodb_trx_fields_info;
677 	schema->fill_table = trx_i_s_common_fill_table;
678 
679 	DBUG_RETURN(0);
680 }
681 
682 static struct st_mysql_information_schema	i_s_info =
683 {
684 	MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
685 };
686 
687 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_trx =
688 {
689 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
690 	/* int */
691 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
692 
693 	/* pointer to type-specific plugin descriptor */
694 	/* void* */
695 	STRUCT_FLD(info, &i_s_info),
696 
697 	/* plugin name */
698 	/* const char* */
699 	STRUCT_FLD(name, "INNODB_TRX"),
700 
701 	/* plugin author (for SHOW PLUGINS) */
702 	/* const char* */
703 	STRUCT_FLD(author, plugin_author),
704 
705 	/* general descriptive text (for SHOW PLUGINS) */
706 	/* const char* */
707 	STRUCT_FLD(descr, "InnoDB transactions"),
708 
709 	/* the plugin license (PLUGIN_LICENSE_XXX) */
710 	/* int */
711 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
712 
713 	/* the function to invoke when plugin is loaded */
714 	/* int (*)(void*); */
715 	STRUCT_FLD(init, innodb_trx_init),
716 
717 	/* the function to invoke when plugin is unloaded */
718 	/* int (*)(void*); */
719 	STRUCT_FLD(deinit, i_s_common_deinit),
720 
721 	/* plugin version (for SHOW PLUGINS) */
722 	/* unsigned int */
723 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
724 
725 	/* struct st_mysql_show_var* */
726 	STRUCT_FLD(status_vars, NULL),
727 
728 	/* struct st_mysql_sys_var** */
729 	STRUCT_FLD(system_vars, NULL),
730 
731 	/* reserved for dependency checking */
732 	/* void* */
733 	STRUCT_FLD(__reserved1, NULL),
734 
735 	/* Plugin flags */
736 	/* unsigned long */
737 	STRUCT_FLD(flags, 0UL),
738 };
739 
740 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
741 static ST_FIELD_INFO	innodb_locks_fields_info[] =
742 {
743 #define IDX_LOCK_ID		0
744 	{STRUCT_FLD(field_name,		"lock_id"),
745 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
746 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
747 	 STRUCT_FLD(value,		0),
748 	 STRUCT_FLD(field_flags,	0),
749 	 STRUCT_FLD(old_name,		""),
750 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
751 
752 #define IDX_LOCK_TRX_ID		1
753 	{STRUCT_FLD(field_name,		"lock_trx_id"),
754 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
755 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
756 	 STRUCT_FLD(value,		0),
757 	 STRUCT_FLD(field_flags,	0),
758 	 STRUCT_FLD(old_name,		""),
759 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
760 
761 #define IDX_LOCK_MODE		2
762 	{STRUCT_FLD(field_name,		"lock_mode"),
763 	 /* S[,GAP] X[,GAP] IS[,GAP] IX[,GAP] AUTO_INC UNKNOWN */
764 	 STRUCT_FLD(field_length,	32),
765 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
766 	 STRUCT_FLD(value,		0),
767 	 STRUCT_FLD(field_flags,	0),
768 	 STRUCT_FLD(old_name,		""),
769 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
770 
771 #define IDX_LOCK_TYPE		3
772 	{STRUCT_FLD(field_name,		"lock_type"),
773 	 STRUCT_FLD(field_length,	32 /* RECORD|TABLE|UNKNOWN */),
774 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
775 	 STRUCT_FLD(value,		0),
776 	 STRUCT_FLD(field_flags,	0),
777 	 STRUCT_FLD(old_name,		""),
778 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
779 
780 #define IDX_LOCK_TABLE		4
781 	{STRUCT_FLD(field_name,		"lock_table"),
782 	 STRUCT_FLD(field_length,	1024),
783 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
784 	 STRUCT_FLD(value,		0),
785 	 STRUCT_FLD(field_flags,	0),
786 	 STRUCT_FLD(old_name,		""),
787 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
788 
789 #define IDX_LOCK_INDEX		5
790 	{STRUCT_FLD(field_name,		"lock_index"),
791 	 STRUCT_FLD(field_length,	1024),
792 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
793 	 STRUCT_FLD(value,		0),
794 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
795 	 STRUCT_FLD(old_name,		""),
796 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
797 
798 #define IDX_LOCK_SPACE		6
799 	{STRUCT_FLD(field_name,		"lock_space"),
800 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
801 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
802 	 STRUCT_FLD(value,		0),
803 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
804 	 STRUCT_FLD(old_name,		""),
805 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
806 
807 #define IDX_LOCK_PAGE		7
808 	{STRUCT_FLD(field_name,		"lock_page"),
809 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
810 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
811 	 STRUCT_FLD(value,		0),
812 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
813 	 STRUCT_FLD(old_name,		""),
814 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
815 
816 #define IDX_LOCK_REC		8
817 	{STRUCT_FLD(field_name,		"lock_rec"),
818 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
819 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
820 	 STRUCT_FLD(value,		0),
821 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
822 	 STRUCT_FLD(old_name,		""),
823 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
824 
825 #define IDX_LOCK_DATA		9
826 	{STRUCT_FLD(field_name,		"lock_data"),
827 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_DATA_MAX_LEN),
828 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
829 	 STRUCT_FLD(value,		0),
830 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
831 	 STRUCT_FLD(old_name,		""),
832 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
833 
834 	END_OF_ST_FIELD_INFO
835 };
836 
837 /*******************************************************************//**
838 Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_locks
839 table with it.
840 @return	0 on success */
841 static
842 int
fill_innodb_locks_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)843 fill_innodb_locks_from_cache(
844 /*=========================*/
845 	trx_i_s_cache_t*	cache,	/*!< in: cache to read from */
846 	THD*			thd,	/*!< in: MySQL client connection */
847 	TABLE*			table)	/*!< in/out: fill this table */
848 {
849 	Field**	fields;
850 	ulint	rows_num;
851 	char	lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
852 	ulint	i;
853 
854 	DBUG_ENTER("fill_innodb_locks_from_cache");
855 
856 	fields = table->field;
857 
858 	rows_num = trx_i_s_cache_get_rows_used(cache,
859 					       I_S_INNODB_LOCKS);
860 
861 	for (i = 0; i < rows_num; i++) {
862 
863 		i_s_locks_row_t*	row;
864 		char			buf[MAX_FULL_NAME_LEN + 1];
865 		const char*		bufend;
866 
867 		char			lock_trx_id[TRX_ID_MAX_LEN + 1];
868 
869 		row = (i_s_locks_row_t*)
870 			trx_i_s_cache_get_nth_row(
871 				cache, I_S_INNODB_LOCKS, i);
872 
873 		/* lock_id */
874 		trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
875 		OK(field_store_string(fields[IDX_LOCK_ID],
876 				      lock_id));
877 
878 		/* lock_trx_id */
879 		ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
880 			    TRX_ID_FMT, row->lock_trx_id);
881 		OK(field_store_string(fields[IDX_LOCK_TRX_ID], lock_trx_id));
882 
883 		/* lock_mode */
884 		OK(field_store_string(fields[IDX_LOCK_MODE],
885 				      row->lock_mode));
886 
887 		/* lock_type */
888 		OK(field_store_string(fields[IDX_LOCK_TYPE],
889 				      row->lock_type));
890 
891 		/* lock_table */
892 		bufend = innobase_convert_name(buf, sizeof(buf),
893 					       row->lock_table,
894 					       strlen(row->lock_table),
895 					       thd, TRUE);
896 		OK(fields[IDX_LOCK_TABLE]->store(buf, bufend - buf,
897 						 system_charset_info));
898 
899 		/* lock_index */
900 		if (row->lock_index != NULL) {
901 
902 			bufend = innobase_convert_name(buf, sizeof(buf),
903 						       row->lock_index,
904 						       strlen(row->lock_index),
905 						       thd, FALSE);
906 			OK(fields[IDX_LOCK_INDEX]->store(buf, bufend - buf,
907 							 system_charset_info));
908 			fields[IDX_LOCK_INDEX]->set_notnull();
909 		} else {
910 
911 			fields[IDX_LOCK_INDEX]->set_null();
912 		}
913 
914 		/* lock_space */
915 		OK(field_store_ulint(fields[IDX_LOCK_SPACE],
916 				     row->lock_space));
917 
918 		/* lock_page */
919 		OK(field_store_ulint(fields[IDX_LOCK_PAGE],
920 				     row->lock_page));
921 
922 		/* lock_rec */
923 		OK(field_store_ulint(fields[IDX_LOCK_REC],
924 				     row->lock_rec));
925 
926 		/* lock_data */
927 		OK(field_store_string(fields[IDX_LOCK_DATA],
928 				      row->lock_data));
929 
930 		OK(schema_table_store_record(thd, table));
931 	}
932 
933 	DBUG_RETURN(0);
934 }
935 
936 /*******************************************************************//**
937 Bind the dynamic table INFORMATION_SCHEMA.innodb_locks
938 @return	0 on success */
939 static
940 int
innodb_locks_init(void * p)941 innodb_locks_init(
942 /*==============*/
943 	void*	p)	/*!< in/out: table schema object */
944 {
945 	ST_SCHEMA_TABLE*	schema;
946 
947 	DBUG_ENTER("innodb_locks_init");
948 
949 	schema = (ST_SCHEMA_TABLE*) p;
950 
951 	schema->fields_info = innodb_locks_fields_info;
952 	schema->fill_table = trx_i_s_common_fill_table;
953 
954 	DBUG_RETURN(0);
955 }
956 
957 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_locks =
958 {
959 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
960 	/* int */
961 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
962 
963 	/* pointer to type-specific plugin descriptor */
964 	/* void* */
965 	STRUCT_FLD(info, &i_s_info),
966 
967 	/* plugin name */
968 	/* const char* */
969 	STRUCT_FLD(name, "INNODB_LOCKS"),
970 
971 	/* plugin author (for SHOW PLUGINS) */
972 	/* const char* */
973 	STRUCT_FLD(author, plugin_author),
974 
975 	/* general descriptive text (for SHOW PLUGINS) */
976 	/* const char* */
977 	STRUCT_FLD(descr, "InnoDB conflicting locks"),
978 
979 	/* the plugin license (PLUGIN_LICENSE_XXX) */
980 	/* int */
981 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
982 
983 	/* the function to invoke when plugin is loaded */
984 	/* int (*)(void*); */
985 	STRUCT_FLD(init, innodb_locks_init),
986 
987 	/* the function to invoke when plugin is unloaded */
988 	/* int (*)(void*); */
989 	STRUCT_FLD(deinit, i_s_common_deinit),
990 
991 	/* plugin version (for SHOW PLUGINS) */
992 	/* unsigned int */
993 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
994 
995 	/* struct st_mysql_show_var* */
996 	STRUCT_FLD(status_vars, NULL),
997 
998 	/* struct st_mysql_sys_var** */
999 	STRUCT_FLD(system_vars, NULL),
1000 
1001 	/* reserved for dependency checking */
1002 	/* void* */
1003 	STRUCT_FLD(__reserved1, NULL),
1004 
1005 	/* Plugin flags */
1006 	/* unsigned long */
1007 	STRUCT_FLD(flags, 0UL),
1008 };
1009 
1010 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
1011 static ST_FIELD_INFO	innodb_lock_waits_fields_info[] =
1012 {
1013 #define IDX_REQUESTING_TRX_ID	0
1014 	{STRUCT_FLD(field_name,		"requesting_trx_id"),
1015 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
1016 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1017 	 STRUCT_FLD(value,		0),
1018 	 STRUCT_FLD(field_flags,	0),
1019 	 STRUCT_FLD(old_name,		""),
1020 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1021 
1022 #define IDX_REQUESTED_LOCK_ID	1
1023 	{STRUCT_FLD(field_name,		"requested_lock_id"),
1024 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
1025 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1026 	 STRUCT_FLD(value,		0),
1027 	 STRUCT_FLD(field_flags,	0),
1028 	 STRUCT_FLD(old_name,		""),
1029 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1030 
1031 #define IDX_BLOCKING_TRX_ID	2
1032 	{STRUCT_FLD(field_name,		"blocking_trx_id"),
1033 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
1034 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1035 	 STRUCT_FLD(value,		0),
1036 	 STRUCT_FLD(field_flags,	0),
1037 	 STRUCT_FLD(old_name,		""),
1038 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1039 
1040 #define IDX_BLOCKING_LOCK_ID	3
1041 	{STRUCT_FLD(field_name,		"blocking_lock_id"),
1042 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
1043 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1044 	 STRUCT_FLD(value,		0),
1045 	 STRUCT_FLD(field_flags,	0),
1046 	 STRUCT_FLD(old_name,		""),
1047 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1048 
1049 	END_OF_ST_FIELD_INFO
1050 };
1051 
1052 /*******************************************************************//**
1053 Read data from cache buffer and fill the
1054 INFORMATION_SCHEMA.innodb_lock_waits table with it.
1055 @return	0 on success */
1056 static
1057 int
fill_innodb_lock_waits_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)1058 fill_innodb_lock_waits_from_cache(
1059 /*==============================*/
1060 	trx_i_s_cache_t*	cache,	/*!< in: cache to read from */
1061 	THD*			thd,	/*!< in: used to call
1062 					schema_table_store_record() */
1063 	TABLE*			table)	/*!< in/out: fill this table */
1064 {
1065 	Field**	fields;
1066 	ulint	rows_num;
1067 	char	requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
1068 	char	blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
1069 	ulint	i;
1070 
1071 	DBUG_ENTER("fill_innodb_lock_waits_from_cache");
1072 
1073 	fields = table->field;
1074 
1075 	rows_num = trx_i_s_cache_get_rows_used(cache,
1076 					       I_S_INNODB_LOCK_WAITS);
1077 
1078 	for (i = 0; i < rows_num; i++) {
1079 
1080 		i_s_lock_waits_row_t*	row;
1081 
1082 		char	requesting_trx_id[TRX_ID_MAX_LEN + 1];
1083 		char	blocking_trx_id[TRX_ID_MAX_LEN + 1];
1084 
1085 		row = (i_s_lock_waits_row_t*)
1086 			trx_i_s_cache_get_nth_row(
1087 				cache, I_S_INNODB_LOCK_WAITS, i);
1088 
1089 		/* requesting_trx_id */
1090 		ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
1091 			    TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
1092 		OK(field_store_string(fields[IDX_REQUESTING_TRX_ID],
1093 				      requesting_trx_id));
1094 
1095 		/* requested_lock_id */
1096 		OK(field_store_string(
1097 			   fields[IDX_REQUESTED_LOCK_ID],
1098 			   trx_i_s_create_lock_id(
1099 				   row->requested_lock_row,
1100 				   requested_lock_id,
1101 				   sizeof(requested_lock_id))));
1102 
1103 		/* blocking_trx_id */
1104 		ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
1105 			    TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
1106 		OK(field_store_string(fields[IDX_BLOCKING_TRX_ID],
1107 				      blocking_trx_id));
1108 
1109 		/* blocking_lock_id */
1110 		OK(field_store_string(
1111 			   fields[IDX_BLOCKING_LOCK_ID],
1112 			   trx_i_s_create_lock_id(
1113 				   row->blocking_lock_row,
1114 				   blocking_lock_id,
1115 				   sizeof(blocking_lock_id))));
1116 
1117 		OK(schema_table_store_record(thd, table));
1118 	}
1119 
1120 	DBUG_RETURN(0);
1121 }
1122 
1123 /*******************************************************************//**
1124 Bind the dynamic table INFORMATION_SCHEMA.innodb_lock_waits
1125 @return	0 on success */
1126 static
1127 int
innodb_lock_waits_init(void * p)1128 innodb_lock_waits_init(
1129 /*===================*/
1130 	void*	p)	/*!< in/out: table schema object */
1131 {
1132 	ST_SCHEMA_TABLE*	schema;
1133 
1134 	DBUG_ENTER("innodb_lock_waits_init");
1135 
1136 	schema = (ST_SCHEMA_TABLE*) p;
1137 
1138 	schema->fields_info = innodb_lock_waits_fields_info;
1139 	schema->fill_table = trx_i_s_common_fill_table;
1140 
1141 	DBUG_RETURN(0);
1142 }
1143 
1144 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_lock_waits =
1145 {
1146 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1147 	/* int */
1148 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1149 
1150 	/* pointer to type-specific plugin descriptor */
1151 	/* void* */
1152 	STRUCT_FLD(info, &i_s_info),
1153 
1154 	/* plugin name */
1155 	/* const char* */
1156 	STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
1157 
1158 	/* plugin author (for SHOW PLUGINS) */
1159 	/* const char* */
1160 	STRUCT_FLD(author, plugin_author),
1161 
1162 	/* general descriptive text (for SHOW PLUGINS) */
1163 	/* const char* */
1164 	STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
1165 
1166 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1167 	/* int */
1168 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1169 
1170 	/* the function to invoke when plugin is loaded */
1171 	/* int (*)(void*); */
1172 	STRUCT_FLD(init, innodb_lock_waits_init),
1173 
1174 	/* the function to invoke when plugin is unloaded */
1175 	/* int (*)(void*); */
1176 	STRUCT_FLD(deinit, i_s_common_deinit),
1177 
1178 	/* plugin version (for SHOW PLUGINS) */
1179 	/* unsigned int */
1180 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1181 
1182 	/* struct st_mysql_show_var* */
1183 	STRUCT_FLD(status_vars, NULL),
1184 
1185 	/* struct st_mysql_sys_var** */
1186 	STRUCT_FLD(system_vars, NULL),
1187 
1188 	/* reserved for dependency checking */
1189 	/* void* */
1190 	STRUCT_FLD(__reserved1, NULL),
1191 
1192 	/* Plugin flags */
1193 	/* unsigned long */
1194 	STRUCT_FLD(flags, 0UL),
1195 };
1196 
1197 /*******************************************************************//**
1198 Common function to fill any of the dynamic tables:
1199 INFORMATION_SCHEMA.innodb_trx
1200 INFORMATION_SCHEMA.innodb_locks
1201 INFORMATION_SCHEMA.innodb_lock_waits
1202 @return	0 on success */
1203 static
1204 int
trx_i_s_common_fill_table(THD * thd,TABLE_LIST * tables,COND * cond)1205 trx_i_s_common_fill_table(
1206 /*======================*/
1207 	THD*		thd,	/*!< in: thread */
1208 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1209 	COND*		cond)	/*!< in: condition (not used) */
1210 {
1211 	const char*		table_name;
1212 	int			ret;
1213 	trx_i_s_cache_t*	cache;
1214 
1215 	DBUG_ENTER("trx_i_s_common_fill_table");
1216 
1217 	/* deny access to non-superusers */
1218 	if (check_global_access(thd, PROCESS_ACL)) {
1219 
1220 		DBUG_RETURN(0);
1221 	}
1222 
1223 	/* minimize the number of places where global variables are
1224 	referenced */
1225 	cache = trx_i_s_cache;
1226 
1227 	/* which table we have to fill? */
1228 	table_name = tables->schema_table_name;
1229 	/* or table_name = tables->schema_table->table_name; */
1230 
1231 	RETURN_IF_INNODB_NOT_STARTED(table_name);
1232 
1233 	/* update the cache */
1234 	trx_i_s_cache_start_write(cache);
1235 	trx_i_s_possibly_fetch_data_into_cache(cache);
1236 	trx_i_s_cache_end_write(cache);
1237 
1238 	if (trx_i_s_cache_is_truncated(cache)) {
1239 
1240 		/* XXX show warning to user if possible */
1241 		fprintf(stderr, "Warning: data in %s truncated due to "
1242 			"memory limit of %d bytes\n", table_name,
1243 			TRX_I_S_MEM_LIMIT);
1244 	}
1245 
1246 	ret = 0;
1247 
1248 	trx_i_s_cache_start_read(cache);
1249 
1250 	if (innobase_strcasecmp(table_name, "innodb_trx") == 0) {
1251 
1252 		if (fill_innodb_trx_from_cache(
1253 			cache, thd, tables->table) != 0) {
1254 
1255 			ret = 1;
1256 		}
1257 
1258 	} else if (innobase_strcasecmp(table_name, "innodb_locks") == 0) {
1259 
1260 		if (fill_innodb_locks_from_cache(
1261 			cache, thd, tables->table) != 0) {
1262 
1263 			ret = 1;
1264 		}
1265 
1266 	} else if (innobase_strcasecmp(table_name, "innodb_lock_waits") == 0) {
1267 
1268 		if (fill_innodb_lock_waits_from_cache(
1269 			cache, thd, tables->table) != 0) {
1270 
1271 			ret = 1;
1272 		}
1273 
1274 	} else {
1275 
1276 		/* huh! what happened!? */
1277 		fprintf(stderr,
1278 			"InnoDB: trx_i_s_common_fill_table() was "
1279 			"called to fill unknown table: %s.\n"
1280 			"This function only knows how to fill "
1281 			"innodb_trx, innodb_locks and "
1282 			"innodb_lock_waits tables.\n", table_name);
1283 
1284 		ret = 1;
1285 	}
1286 
1287 	trx_i_s_cache_end_read(cache);
1288 
1289 #if 0
1290 	DBUG_RETURN(ret);
1291 #else
1292 	/* if this function returns something else than 0 then a
1293 	deadlock occurs between the mysqld server and mysql client,
1294 	see http://bugs.mysql.com/29900 ; when that bug is resolved
1295 	we can enable the DBUG_RETURN(ret) above */
1296 	ret++;  // silence a gcc46 warning
1297 	DBUG_RETURN(0);
1298 #endif
1299 }
1300 
1301 /* Fields of the dynamic table information_schema.innodb_cmp. */
1302 static ST_FIELD_INFO	i_s_cmp_fields_info[] =
1303 {
1304 	{STRUCT_FLD(field_name,		"page_size"),
1305 	 STRUCT_FLD(field_length,	5),
1306 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1307 	 STRUCT_FLD(value,		0),
1308 	 STRUCT_FLD(field_flags,	0),
1309 	 STRUCT_FLD(old_name,		"Compressed Page Size"),
1310 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1311 
1312 	{STRUCT_FLD(field_name,		"compress_ops"),
1313 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1314 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1315 	 STRUCT_FLD(value,		0),
1316 	 STRUCT_FLD(field_flags,	0),
1317 	 STRUCT_FLD(old_name,		"Total Number of Compressions"),
1318 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1319 
1320 	{STRUCT_FLD(field_name,		"compress_ops_ok"),
1321 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1322 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1323 	 STRUCT_FLD(value,		0),
1324 	 STRUCT_FLD(field_flags,	0),
1325 	 STRUCT_FLD(old_name,		"Total Number of"
1326 					" Successful Compressions"),
1327 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1328 
1329 	{STRUCT_FLD(field_name,		"compress_time"),
1330 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1331 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1332 	 STRUCT_FLD(value,		0),
1333 	 STRUCT_FLD(field_flags,	0),
1334 	 STRUCT_FLD(old_name,		"Total Duration of Compressions,"
1335 		    " in Seconds"),
1336 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1337 
1338 	{STRUCT_FLD(field_name,		"uncompress_ops"),
1339 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1340 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1341 	 STRUCT_FLD(value,		0),
1342 	 STRUCT_FLD(field_flags,	0),
1343 	 STRUCT_FLD(old_name,		"Total Number of Decompressions"),
1344 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1345 
1346 	{STRUCT_FLD(field_name,		"uncompress_time"),
1347 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1348 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1349 	 STRUCT_FLD(value,		0),
1350 	 STRUCT_FLD(field_flags,	0),
1351 	 STRUCT_FLD(old_name,		"Total Duration of Decompressions,"
1352 		    " in Seconds"),
1353 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1354 
1355 	END_OF_ST_FIELD_INFO
1356 };
1357 
1358 
1359 /*******************************************************************//**
1360 Fill the dynamic table information_schema.innodb_cmp or
1361 innodb_cmp_reset.
1362 @return	0 on success, 1 on failure */
1363 static
1364 int
i_s_cmp_fill_low(THD * thd,TABLE_LIST * tables,COND * cond,ibool reset)1365 i_s_cmp_fill_low(
1366 /*=============*/
1367 	THD*		thd,	/*!< in: thread */
1368 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1369 	COND*		cond,	/*!< in: condition (ignored) */
1370 	ibool		reset)	/*!< in: TRUE=reset cumulated counts */
1371 {
1372 	TABLE*	table	= (TABLE *) tables->table;
1373 	int	status	= 0;
1374 
1375 	DBUG_ENTER("i_s_cmp_fill_low");
1376 
1377 	/* deny access to non-superusers */
1378 	if (check_global_access(thd, PROCESS_ACL)) {
1379 
1380 		DBUG_RETURN(0);
1381 	}
1382 
1383 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
1384 
1385 	for (uint i = 0; i < PAGE_ZIP_NUM_SSIZE - 1; i++) {
1386 		page_zip_stat_t*	zip_stat = &page_zip_stat[i];
1387 
1388 		table->field[0]->store(PAGE_ZIP_MIN_SIZE << i);
1389 
1390 		/* The cumulated counts are not protected by any
1391 		mutex.  Thus, some operation in page0zip.c could
1392 		increment a counter between the time we read it and
1393 		clear it.  We could introduce mutex protection, but it
1394 		could cause a measureable performance hit in
1395 		page0zip.c. */
1396 		table->field[1]->store(zip_stat->compressed);
1397 		table->field[2]->store(zip_stat->compressed_ok);
1398 		table->field[3]->store(
1399 			(ulong) (zip_stat->compressed_usec / 1000000));
1400 		table->field[4]->store(zip_stat->decompressed);
1401 		table->field[5]->store(
1402 			(ulong) (zip_stat->decompressed_usec / 1000000));
1403 
1404 		if (reset) {
1405 			memset(zip_stat, 0, sizeof *zip_stat);
1406 		}
1407 
1408 		if (schema_table_store_record(thd, table)) {
1409 			status = 1;
1410 			break;
1411 		}
1412 	}
1413 
1414 	DBUG_RETURN(status);
1415 }
1416 
1417 /*******************************************************************//**
1418 Fill the dynamic table information_schema.innodb_cmp.
1419 @return	0 on success, 1 on failure */
1420 static
1421 int
i_s_cmp_fill(THD * thd,TABLE_LIST * tables,COND * cond)1422 i_s_cmp_fill(
1423 /*=========*/
1424 	THD*		thd,	/*!< in: thread */
1425 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1426 	COND*		cond)	/*!< in: condition (ignored) */
1427 {
1428 	return(i_s_cmp_fill_low(thd, tables, cond, FALSE));
1429 }
1430 
1431 /*******************************************************************//**
1432 Fill the dynamic table information_schema.innodb_cmp_reset.
1433 @return	0 on success, 1 on failure */
1434 static
1435 int
i_s_cmp_reset_fill(THD * thd,TABLE_LIST * tables,COND * cond)1436 i_s_cmp_reset_fill(
1437 /*===============*/
1438 	THD*		thd,	/*!< in: thread */
1439 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1440 	COND*		cond)	/*!< in: condition (ignored) */
1441 {
1442 	return(i_s_cmp_fill_low(thd, tables, cond, TRUE));
1443 }
1444 
1445 /*******************************************************************//**
1446 Bind the dynamic table information_schema.innodb_cmp.
1447 @return	0 on success */
1448 static
1449 int
i_s_cmp_init(void * p)1450 i_s_cmp_init(
1451 /*=========*/
1452 	void*	p)	/*!< in/out: table schema object */
1453 {
1454 	DBUG_ENTER("i_s_cmp_init");
1455 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1456 
1457 	schema->fields_info = i_s_cmp_fields_info;
1458 	schema->fill_table = i_s_cmp_fill;
1459 
1460 	DBUG_RETURN(0);
1461 }
1462 
1463 /*******************************************************************//**
1464 Bind the dynamic table information_schema.innodb_cmp_reset.
1465 @return	0 on success */
1466 static
1467 int
i_s_cmp_reset_init(void * p)1468 i_s_cmp_reset_init(
1469 /*===============*/
1470 	void*	p)	/*!< in/out: table schema object */
1471 {
1472 	DBUG_ENTER("i_s_cmp_reset_init");
1473 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1474 
1475 	schema->fields_info = i_s_cmp_fields_info;
1476 	schema->fill_table = i_s_cmp_reset_fill;
1477 
1478 	DBUG_RETURN(0);
1479 }
1480 
1481 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmp =
1482 {
1483 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1484 	/* int */
1485 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1486 
1487 	/* pointer to type-specific plugin descriptor */
1488 	/* void* */
1489 	STRUCT_FLD(info, &i_s_info),
1490 
1491 	/* plugin name */
1492 	/* const char* */
1493 	STRUCT_FLD(name, "INNODB_CMP"),
1494 
1495 	/* plugin author (for SHOW PLUGINS) */
1496 	/* const char* */
1497 	STRUCT_FLD(author, plugin_author),
1498 
1499 	/* general descriptive text (for SHOW PLUGINS) */
1500 	/* const char* */
1501 	STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
1502 
1503 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1504 	/* int */
1505 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1506 
1507 	/* the function to invoke when plugin is loaded */
1508 	/* int (*)(void*); */
1509 	STRUCT_FLD(init, i_s_cmp_init),
1510 
1511 	/* the function to invoke when plugin is unloaded */
1512 	/* int (*)(void*); */
1513 	STRUCT_FLD(deinit, i_s_common_deinit),
1514 
1515 	/* plugin version (for SHOW PLUGINS) */
1516 	/* unsigned int */
1517 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1518 
1519 	/* struct st_mysql_show_var* */
1520 	STRUCT_FLD(status_vars, NULL),
1521 
1522 	/* struct st_mysql_sys_var** */
1523 	STRUCT_FLD(system_vars, NULL),
1524 
1525 	/* reserved for dependency checking */
1526 	/* void* */
1527 	STRUCT_FLD(__reserved1, NULL),
1528 
1529 	/* Plugin flags */
1530 	/* unsigned long */
1531 	STRUCT_FLD(flags, 0UL),
1532 };
1533 
1534 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmp_reset =
1535 {
1536 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1537 	/* int */
1538 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1539 
1540 	/* pointer to type-specific plugin descriptor */
1541 	/* void* */
1542 	STRUCT_FLD(info, &i_s_info),
1543 
1544 	/* plugin name */
1545 	/* const char* */
1546 	STRUCT_FLD(name, "INNODB_CMP_RESET"),
1547 
1548 	/* plugin author (for SHOW PLUGINS) */
1549 	/* const char* */
1550 	STRUCT_FLD(author, plugin_author),
1551 
1552 	/* general descriptive text (for SHOW PLUGINS) */
1553 	/* const char* */
1554 	STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
1555 		   " reset cumulated counts"),
1556 
1557 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1558 	/* int */
1559 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1560 
1561 	/* the function to invoke when plugin is loaded */
1562 	/* int (*)(void*); */
1563 	STRUCT_FLD(init, i_s_cmp_reset_init),
1564 
1565 	/* the function to invoke when plugin is unloaded */
1566 	/* int (*)(void*); */
1567 	STRUCT_FLD(deinit, i_s_common_deinit),
1568 
1569 	/* plugin version (for SHOW PLUGINS) */
1570 	/* unsigned int */
1571 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1572 
1573 	/* struct st_mysql_show_var* */
1574 	STRUCT_FLD(status_vars, NULL),
1575 
1576 	/* struct st_mysql_sys_var** */
1577 	STRUCT_FLD(system_vars, NULL),
1578 
1579 	/* reserved for dependency checking */
1580 	/* void* */
1581 	STRUCT_FLD(__reserved1, NULL),
1582 
1583 	/* Plugin flags */
1584 	/* unsigned long */
1585 	STRUCT_FLD(flags, 0UL),
1586 };
1587 
1588 /* Fields of the dynamic table information_schema.innodb_cmpmem. */
1589 static ST_FIELD_INFO	i_s_cmpmem_fields_info[] =
1590 {
1591 	{STRUCT_FLD(field_name,		"page_size"),
1592 	 STRUCT_FLD(field_length,	5),
1593 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1594 	 STRUCT_FLD(value,		0),
1595 	 STRUCT_FLD(field_flags,	0),
1596 	 STRUCT_FLD(old_name,		"Buddy Block Size"),
1597 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1598 
1599 	{STRUCT_FLD(field_name,		"buffer_pool_instance"),
1600 	STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1601 	STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1602 	STRUCT_FLD(value,		0),
1603 	STRUCT_FLD(field_flags,		0),
1604 	STRUCT_FLD(old_name,		"Buffer Pool Id"),
1605 	STRUCT_FLD(open_method,		SKIP_OPEN_TABLE)},
1606 
1607 	{STRUCT_FLD(field_name,		"pages_used"),
1608 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1609 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1610 	 STRUCT_FLD(value,		0),
1611 	 STRUCT_FLD(field_flags,	0),
1612 	 STRUCT_FLD(old_name,		"Currently in Use"),
1613 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1614 
1615 	{STRUCT_FLD(field_name,		"pages_free"),
1616 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1617 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1618 	 STRUCT_FLD(value,		0),
1619 	 STRUCT_FLD(field_flags,	0),
1620 	 STRUCT_FLD(old_name,		"Currently Available"),
1621 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1622 
1623 	{STRUCT_FLD(field_name,		"relocation_ops"),
1624 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1625 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1626 	 STRUCT_FLD(value,		0),
1627 	 STRUCT_FLD(field_flags,	0),
1628 	 STRUCT_FLD(old_name,		"Total Number of Relocations"),
1629 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1630 
1631 	{STRUCT_FLD(field_name,		"relocation_time"),
1632 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1633 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1634 	 STRUCT_FLD(value,		0),
1635 	 STRUCT_FLD(field_flags,	0),
1636 	 STRUCT_FLD(old_name,		"Total Duration of Relocations,"
1637 		    			" in Seconds"),
1638 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1639 
1640 	END_OF_ST_FIELD_INFO
1641 };
1642 
1643 /*******************************************************************//**
1644 Fill the dynamic table information_schema.innodb_cmpmem or
1645 innodb_cmpmem_reset.
1646 @return	0 on success, 1 on failure */
1647 static
1648 int
i_s_cmpmem_fill_low(THD * thd,TABLE_LIST * tables,COND * cond,ibool reset)1649 i_s_cmpmem_fill_low(
1650 /*================*/
1651 	THD*		thd,	/*!< in: thread */
1652 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1653 	COND*		cond,	/*!< in: condition (ignored) */
1654 	ibool		reset)	/*!< in: TRUE=reset cumulated counts */
1655 {
1656 	int		status = 0;
1657 	TABLE*	table	= (TABLE *) tables->table;
1658 
1659 	DBUG_ENTER("i_s_cmpmem_fill_low");
1660 
1661 	/* deny access to non-superusers */
1662 	if (check_global_access(thd, PROCESS_ACL)) {
1663 
1664 		DBUG_RETURN(0);
1665 	}
1666 
1667 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
1668 
1669 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
1670 		buf_pool_t*	buf_pool;
1671 
1672 		status	= 0;
1673 
1674 		buf_pool = buf_pool_from_array(i);
1675 
1676 		buf_pool_mutex_enter(buf_pool);
1677 
1678 		for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
1679 			buf_buddy_stat_t*	buddy_stat;
1680 
1681 			buddy_stat = &buf_pool->buddy_stat[x];
1682 
1683 			table->field[0]->store(BUF_BUDDY_LOW << x);
1684 			table->field[1]->store(i);
1685 			table->field[2]->store(buddy_stat->used);
1686 			table->field[3]->store(UNIV_LIKELY(x < BUF_BUDDY_SIZES)
1687 				? UT_LIST_GET_LEN(buf_pool->zip_free[x])
1688 				: 0);
1689 			table->field[4]->store((longlong)
1690 			buddy_stat->relocated, true);
1691 			table->field[5]->store(
1692 				(ulong) (buddy_stat->relocated_usec / 1000000));
1693 
1694 			if (reset) {
1695 				/* This is protected by buf_pool->mutex. */
1696 				buddy_stat->relocated = 0;
1697 				buddy_stat->relocated_usec = 0;
1698 			}
1699 
1700 			if (schema_table_store_record(thd, table)) {
1701 				status = 1;
1702 				break;
1703 			}
1704 		}
1705 
1706 		buf_pool_mutex_exit(buf_pool);
1707 
1708 		if (status) {
1709 			break;
1710 		}
1711 	}
1712 
1713 	DBUG_RETURN(status);
1714 }
1715 
1716 /*******************************************************************//**
1717 Fill the dynamic table information_schema.innodb_cmpmem.
1718 @return	0 on success, 1 on failure */
1719 static
1720 int
i_s_cmpmem_fill(THD * thd,TABLE_LIST * tables,COND * cond)1721 i_s_cmpmem_fill(
1722 /*============*/
1723 	THD*		thd,	/*!< in: thread */
1724 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1725 	COND*		cond)	/*!< in: condition (ignored) */
1726 {
1727 	return(i_s_cmpmem_fill_low(thd, tables, cond, FALSE));
1728 }
1729 
1730 /*******************************************************************//**
1731 Fill the dynamic table information_schema.innodb_cmpmem_reset.
1732 @return	0 on success, 1 on failure */
1733 static
1734 int
i_s_cmpmem_reset_fill(THD * thd,TABLE_LIST * tables,COND * cond)1735 i_s_cmpmem_reset_fill(
1736 /*==================*/
1737 	THD*		thd,	/*!< in: thread */
1738 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1739 	COND*		cond)	/*!< in: condition (ignored) */
1740 {
1741 	return(i_s_cmpmem_fill_low(thd, tables, cond, TRUE));
1742 }
1743 
1744 /*******************************************************************//**
1745 Bind the dynamic table information_schema.innodb_cmpmem.
1746 @return	0 on success */
1747 static
1748 int
i_s_cmpmem_init(void * p)1749 i_s_cmpmem_init(
1750 /*============*/
1751 	void*	p)	/*!< in/out: table schema object */
1752 {
1753 	DBUG_ENTER("i_s_cmpmem_init");
1754 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1755 
1756 	schema->fields_info = i_s_cmpmem_fields_info;
1757 	schema->fill_table = i_s_cmpmem_fill;
1758 
1759 	DBUG_RETURN(0);
1760 }
1761 
1762 /*******************************************************************//**
1763 Bind the dynamic table information_schema.innodb_cmpmem_reset.
1764 @return	0 on success */
1765 static
1766 int
i_s_cmpmem_reset_init(void * p)1767 i_s_cmpmem_reset_init(
1768 /*==================*/
1769 	void*	p)	/*!< in/out: table schema object */
1770 {
1771 	DBUG_ENTER("i_s_cmpmem_reset_init");
1772 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1773 
1774 	schema->fields_info = i_s_cmpmem_fields_info;
1775 	schema->fill_table = i_s_cmpmem_reset_fill;
1776 
1777 	DBUG_RETURN(0);
1778 }
1779 
1780 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmpmem =
1781 {
1782 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1783 	/* int */
1784 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1785 
1786 	/* pointer to type-specific plugin descriptor */
1787 	/* void* */
1788 	STRUCT_FLD(info, &i_s_info),
1789 
1790 	/* plugin name */
1791 	/* const char* */
1792 	STRUCT_FLD(name, "INNODB_CMPMEM"),
1793 
1794 	/* plugin author (for SHOW PLUGINS) */
1795 	/* const char* */
1796 	STRUCT_FLD(author, plugin_author),
1797 
1798 	/* general descriptive text (for SHOW PLUGINS) */
1799 	/* const char* */
1800 	STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
1801 
1802 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1803 	/* int */
1804 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1805 
1806 	/* the function to invoke when plugin is loaded */
1807 	/* int (*)(void*); */
1808 	STRUCT_FLD(init, i_s_cmpmem_init),
1809 
1810 	/* the function to invoke when plugin is unloaded */
1811 	/* int (*)(void*); */
1812 	STRUCT_FLD(deinit, i_s_common_deinit),
1813 
1814 	/* plugin version (for SHOW PLUGINS) */
1815 	/* unsigned int */
1816 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1817 
1818 	/* struct st_mysql_show_var* */
1819 	STRUCT_FLD(status_vars, NULL),
1820 
1821 	/* struct st_mysql_sys_var** */
1822 	STRUCT_FLD(system_vars, NULL),
1823 
1824 	/* reserved for dependency checking */
1825 	/* void* */
1826 	STRUCT_FLD(__reserved1, NULL),
1827 
1828 	/* Plugin flags */
1829 	/* unsigned long */
1830 	STRUCT_FLD(flags, 0UL),
1831 };
1832 
1833 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmpmem_reset =
1834 {
1835 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1836 	/* int */
1837 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1838 
1839 	/* pointer to type-specific plugin descriptor */
1840 	/* void* */
1841 	STRUCT_FLD(info, &i_s_info),
1842 
1843 	/* plugin name */
1844 	/* const char* */
1845 	STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
1846 
1847 	/* plugin author (for SHOW PLUGINS) */
1848 	/* const char* */
1849 	STRUCT_FLD(author, plugin_author),
1850 
1851 	/* general descriptive text (for SHOW PLUGINS) */
1852 	/* const char* */
1853 	STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
1854 		   " reset cumulated counts"),
1855 
1856 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1857 	/* int */
1858 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1859 
1860 	/* the function to invoke when plugin is loaded */
1861 	/* int (*)(void*); */
1862 	STRUCT_FLD(init, i_s_cmpmem_reset_init),
1863 
1864 	/* the function to invoke when plugin is unloaded */
1865 	/* int (*)(void*); */
1866 	STRUCT_FLD(deinit, i_s_common_deinit),
1867 
1868 	/* plugin version (for SHOW PLUGINS) */
1869 	/* unsigned int */
1870 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1871 
1872 	/* struct st_mysql_show_var* */
1873 	STRUCT_FLD(status_vars, NULL),
1874 
1875 	/* struct st_mysql_sys_var** */
1876 	STRUCT_FLD(system_vars, NULL),
1877 
1878 	/* reserved for dependency checking */
1879 	/* void* */
1880 	STRUCT_FLD(__reserved1, NULL),
1881 
1882 	/* Plugin flags */
1883 	/* unsigned long */
1884 	STRUCT_FLD(flags, 0UL),
1885 };
1886 
1887 /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
1888 static ST_FIELD_INFO	i_s_innodb_buffer_stats_fields_info[] =
1889 {
1890 #define IDX_BUF_STATS_POOL_ID		0
1891 	{STRUCT_FLD(field_name,		"POOL_ID"),
1892 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1893 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1894 	 STRUCT_FLD(value,		0),
1895 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1896 	 STRUCT_FLD(old_name,		""),
1897 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1898 
1899 #define IDX_BUF_STATS_POOL_SIZE		1
1900 	{STRUCT_FLD(field_name,		"POOL_SIZE"),
1901 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1902 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1903 	 STRUCT_FLD(value,		0),
1904 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1905 	 STRUCT_FLD(old_name,		""),
1906 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1907 
1908 #define IDX_BUF_STATS_FREE_BUFFERS	2
1909 	{STRUCT_FLD(field_name,		"FREE_BUFFERS"),
1910 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1911 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1912 	 STRUCT_FLD(value,		0),
1913 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1914 	 STRUCT_FLD(old_name,		""),
1915 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1916 
1917 #define IDX_BUF_STATS_LRU_LEN		3
1918 	{STRUCT_FLD(field_name,		"DATABASE_PAGES"),
1919 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1920 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1921 	 STRUCT_FLD(value,		0),
1922 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1923 	 STRUCT_FLD(old_name,		""),
1924 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1925 
1926 #define IDX_BUF_STATS_OLD_LRU_LEN	4
1927 	{STRUCT_FLD(field_name,		"OLD_DATABASE_PAGES"),
1928 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1929 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1930 	 STRUCT_FLD(value,		0),
1931 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1932 	 STRUCT_FLD(old_name,		""),
1933 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1934 
1935 #define IDX_BUF_STATS_FLUSH_LIST_LEN	5
1936 	{STRUCT_FLD(field_name,		"MODIFIED_DATABASE_PAGES"),
1937 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1938 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1939 	 STRUCT_FLD(value,		0),
1940 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1941 	 STRUCT_FLD(old_name,		""),
1942 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1943 
1944 #define IDX_BUF_STATS_PENDING_ZIP	6
1945 	{STRUCT_FLD(field_name,		"PENDING_DECOMPRESS"),
1946 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1947 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1948 	 STRUCT_FLD(value,		0),
1949 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1950 	 STRUCT_FLD(old_name,		""),
1951 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1952 
1953 #define IDX_BUF_STATS_PENDING_READ	7
1954 	{STRUCT_FLD(field_name,		"PENDING_READS"),
1955 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1956 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1957 	 STRUCT_FLD(value,		0),
1958 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1959 	 STRUCT_FLD(old_name,		""),
1960 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1961 
1962 #define IDX_BUF_STATS_FLUSH_LRU		8
1963 	{STRUCT_FLD(field_name,		"PENDING_FLUSH_LRU"),
1964 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1965 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1966 	 STRUCT_FLD(value,		0),
1967 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1968 	 STRUCT_FLD(old_name,		""),
1969 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1970 
1971 #define IDX_BUF_STATS_FLUSH_LIST	9
1972 	{STRUCT_FLD(field_name,		"PENDING_FLUSH_LIST"),
1973 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1974 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1975 	 STRUCT_FLD(value,		0),
1976 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1977 	 STRUCT_FLD(old_name,		""),
1978 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1979 
1980 #define IDX_BUF_STATS_PAGE_YOUNG	10
1981 	{STRUCT_FLD(field_name,		"PAGES_MADE_YOUNG"),
1982 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1983 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1984 	 STRUCT_FLD(value,		0),
1985 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1986 	 STRUCT_FLD(old_name,		""),
1987 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1988 
1989 #define IDX_BUF_STATS_PAGE_NOT_YOUNG	11
1990 	{STRUCT_FLD(field_name,		"PAGES_NOT_MADE_YOUNG"),
1991 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
1992 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
1993 	 STRUCT_FLD(value,		0),
1994 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
1995 	 STRUCT_FLD(old_name,		""),
1996 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1997 
1998 #define	IDX_BUF_STATS_PAGE_YOUNG_RATE	12
1999 	{STRUCT_FLD(field_name,		"PAGES_MADE_YOUNG_RATE"),
2000 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2001 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2002 	 STRUCT_FLD(value,		0),
2003 	 STRUCT_FLD(field_flags,	0),
2004 	 STRUCT_FLD(old_name,		""),
2005 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2006 
2007 #define	IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
2008 	{STRUCT_FLD(field_name,		"PAGES_MADE_NOT_YOUNG_RATE"),
2009 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2010 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2011 	 STRUCT_FLD(value,		0),
2012 	 STRUCT_FLD(field_flags,	0),
2013 	 STRUCT_FLD(old_name,		""),
2014 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2015 
2016 #define IDX_BUF_STATS_PAGE_READ		14
2017 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_READ"),
2018 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2019 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2020 	 STRUCT_FLD(value,		0),
2021 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2022 	 STRUCT_FLD(old_name,		""),
2023 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2024 
2025 #define IDX_BUF_STATS_PAGE_CREATED	15
2026 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_CREATED"),
2027 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2028 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2029 	 STRUCT_FLD(value,		0),
2030 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2031 	 STRUCT_FLD(old_name,		""),
2032 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2033 
2034 #define IDX_BUF_STATS_PAGE_WRITTEN	16
2035 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_WRITTEN"),
2036 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2037 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2038 	 STRUCT_FLD(value,		0),
2039 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2040 	 STRUCT_FLD(old_name,		""),
2041 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2042 
2043 #define	IDX_BUF_STATS_PAGE_READ_RATE	17
2044 	{STRUCT_FLD(field_name,		"PAGES_READ_RATE"),
2045 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2046 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2047 	 STRUCT_FLD(value,		0),
2048 	 STRUCT_FLD(field_flags,	0),
2049 	 STRUCT_FLD(old_name,		""),
2050 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2051 
2052 #define	IDX_BUF_STATS_PAGE_CREATE_RATE	18
2053 	{STRUCT_FLD(field_name,		"PAGES_CREATE_RATE"),
2054 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2055 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2056 	 STRUCT_FLD(value,		0),
2057 	 STRUCT_FLD(field_flags,	0),
2058 	 STRUCT_FLD(old_name,		""),
2059 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2060 
2061 #define	IDX_BUF_STATS_PAGE_WRITTEN_RATE	19
2062 	{STRUCT_FLD(field_name,		"PAGES_WRITTEN_RATE"),
2063 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2064 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2065 	 STRUCT_FLD(value,		0),
2066 	 STRUCT_FLD(field_flags,	0),
2067 	 STRUCT_FLD(old_name,		""),
2068 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2069 
2070 #define IDX_BUF_STATS_GET		20
2071 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_GET"),
2072 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2073 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2074 	 STRUCT_FLD(value,		0),
2075 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2076 	 STRUCT_FLD(old_name,		""),
2077 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2078 
2079 #define IDX_BUF_STATS_HIT_RATE		21
2080 	{STRUCT_FLD(field_name,		"HIT_RATE"),
2081 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2082 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2083 	 STRUCT_FLD(value,		0),
2084 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2085 	 STRUCT_FLD(old_name,		""),
2086 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2087 
2088 #define IDX_BUF_STATS_MADE_YOUNG_PCT	22
2089 	{STRUCT_FLD(field_name,		"YOUNG_MAKE_PER_THOUSAND_GETS"),
2090 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2091 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2092 	 STRUCT_FLD(value,		0),
2093 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2094 	 STRUCT_FLD(old_name,		""),
2095 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2096 
2097 #define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
2098 	{STRUCT_FLD(field_name,		"NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
2099 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2100 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2101 	 STRUCT_FLD(value,		0),
2102 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2103 	 STRUCT_FLD(old_name,		""),
2104 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2105 
2106 #define IDX_BUF_STATS_READ_AHREAD	24
2107 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_READ_AHEAD"),
2108 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2109 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2110 	 STRUCT_FLD(value,		0),
2111 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2112 	 STRUCT_FLD(old_name,		""),
2113 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2114 
2115 #define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
2116 	{STRUCT_FLD(field_name,		"NUMBER_READ_AHEAD_EVICTED"),
2117 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2118 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2119 	 STRUCT_FLD(value,		0),
2120 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2121 	 STRUCT_FLD(old_name,		""),
2122 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2123 
2124 #define	IDX_BUF_STATS_READ_AHEAD_RATE	26
2125 	{STRUCT_FLD(field_name,		"READ_AHEAD_RATE"),
2126 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2127 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2128 	 STRUCT_FLD(value,		0),
2129 	 STRUCT_FLD(field_flags,	0),
2130 	 STRUCT_FLD(old_name,		""),
2131 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2132 
2133 #define	IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
2134 	{STRUCT_FLD(field_name,		"READ_AHEAD_EVICTED_RATE"),
2135 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2136 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2137 	 STRUCT_FLD(value,		0),
2138 	 STRUCT_FLD(field_flags,	0),
2139 	 STRUCT_FLD(old_name,		""),
2140 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2141 
2142 #define IDX_BUF_STATS_LRU_IO_SUM	28
2143 	{STRUCT_FLD(field_name,		"LRU_IO_TOTAL"),
2144 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2145 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2146 	 STRUCT_FLD(value,		0),
2147 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2148 	 STRUCT_FLD(old_name,		""),
2149 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2150 
2151 #define IDX_BUF_STATS_LRU_IO_CUR	29
2152 	{STRUCT_FLD(field_name,		"LRU_IO_CURRENT"),
2153 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2154 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2155 	 STRUCT_FLD(value,		0),
2156 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2157 	 STRUCT_FLD(old_name,		""),
2158 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2159 
2160 #define IDX_BUF_STATS_UNZIP_SUM		30
2161 	{STRUCT_FLD(field_name,		"UNCOMPRESS_TOTAL"),
2162 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2163 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2164 	 STRUCT_FLD(value,		0),
2165 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2166 	 STRUCT_FLD(old_name,		""),
2167 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2168 
2169 #define IDX_BUF_STATS_UNZIP_CUR		31
2170 	{STRUCT_FLD(field_name,		"UNCOMPRESS_CURRENT"),
2171 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2172 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2173 	 STRUCT_FLD(value,		0),
2174 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2175 	 STRUCT_FLD(old_name,		""),
2176 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2177 
2178 	END_OF_ST_FIELD_INFO
2179 };
2180 
2181 /*******************************************************************//**
2182 Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
2183 buffer pool
2184 @return	0 on success, 1 on failure */
2185 static
2186 int
i_s_innodb_stats_fill(THD * thd,TABLE_LIST * tables,const buf_pool_info_t * info)2187 i_s_innodb_stats_fill(
2188 /*==================*/
2189 	THD*			thd,		/*!< in: thread */
2190 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
2191 	const buf_pool_info_t*	info)		/*!< in: buffer pool
2192 						information */
2193 {
2194 	TABLE*			table;
2195 	Field**			fields;
2196 
2197 	DBUG_ENTER("i_s_innodb_stats_fill");
2198 
2199 	table = tables->table;
2200 
2201 	fields = table->field;
2202 
2203 	OK(fields[IDX_BUF_STATS_POOL_ID]->store(info->pool_unique_id));
2204 
2205 	OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(info->pool_size));
2206 
2207 	OK(fields[IDX_BUF_STATS_LRU_LEN]->store(info->lru_len));
2208 
2209 	OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(info->old_lru_len));
2210 
2211 	OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(info->free_list_len));
2212 
2213 	OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
2214 		info->flush_list_len));
2215 
2216 	OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(info->n_pend_unzip));
2217 
2218 	OK(fields[IDX_BUF_STATS_PENDING_READ]->store(info->n_pend_reads));
2219 
2220 	OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(info->n_pending_flush_lru));
2221 
2222 	OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(info->n_pending_flush_list));
2223 
2224 	OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(info->n_pages_made_young));
2225 
2226 	OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
2227 		info->n_pages_not_made_young));
2228 
2229 	OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
2230 		info->page_made_young_rate));
2231 
2232 	OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
2233 		info->page_not_made_young_rate));
2234 
2235 	OK(fields[IDX_BUF_STATS_PAGE_READ]->store(info->n_pages_read));
2236 
2237 	OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(info->n_pages_created));
2238 
2239 	OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(info->n_pages_written));
2240 
2241 	OK(fields[IDX_BUF_STATS_GET]->store(info->n_page_gets));
2242 
2243 	OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(info->pages_read_rate));
2244 
2245 	OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(info->pages_created_rate));
2246 
2247 	OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(info->pages_written_rate));
2248 
2249 	if (info->n_page_get_delta) {
2250 		OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
2251 			1000 - (1000 * info->page_read_delta
2252 				/ info->n_page_get_delta)));
2253 
2254 		OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
2255 			1000 * info->young_making_delta
2256 			/ info->n_page_get_delta));
2257 
2258 		OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
2259 			1000 * info->not_young_making_delta
2260 			/ info->n_page_get_delta));
2261 	} else {
2262 		OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0));
2263 		OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0));
2264 		OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0));
2265 	}
2266 
2267 	OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(info->n_ra_pages_read));
2268 
2269 	OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
2270 		info->n_ra_pages_evicted));
2271 
2272 	OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
2273 		info->pages_readahead_rate));
2274 
2275 	OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
2276 		info->pages_evicted_rate));
2277 
2278 	OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(info->io_sum));
2279 
2280 	OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(info->io_cur));
2281 
2282 	OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(info->unzip_sum));
2283 
2284 	OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store( info->unzip_cur));
2285 
2286 	DBUG_RETURN(schema_table_store_record(thd, table));
2287 }
2288 
2289 /*******************************************************************//**
2290 This is the function that loops through each buffer pool and fetch buffer
2291 pool stats to information schema  table: I_S_INNODB_BUFFER_POOL_STATS
2292 @return	0 on success, 1 on failure */
2293 static
2294 int
i_s_innodb_buffer_stats_fill_table(THD * thd,TABLE_LIST * tables,Item *)2295 i_s_innodb_buffer_stats_fill_table(
2296 /*===============================*/
2297 	THD*		thd,		/*!< in: thread */
2298 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
2299 	Item*		)		/*!< in: condition (ignored) */
2300 {
2301 	int			status	= 0;
2302 	buf_pool_info_t*	pool_info;
2303 
2304 	DBUG_ENTER("i_s_innodb_buffer_fill_general");
2305 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
2306 
2307 	/* Only allow the PROCESS privilege holder to access the stats */
2308 	if (check_global_access(thd, PROCESS_ACL)) {
2309 		DBUG_RETURN(0);
2310 	}
2311 
2312 	pool_info = (buf_pool_info_t*) mem_zalloc(
2313 		srv_buf_pool_instances *  sizeof *pool_info);
2314 
2315 	/* Walk through each buffer pool */
2316 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
2317 		buf_pool_t*		buf_pool;
2318 
2319 		buf_pool = buf_pool_from_array(i);
2320 
2321 		/* Fetch individual buffer pool info */
2322 		buf_stats_get_pool_info(buf_pool, i, pool_info);
2323 
2324 		status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
2325 
2326 		/* If something goes wrong, break and return */
2327 		if (status) {
2328 			break;
2329 		}
2330 	}
2331 
2332 	mem_free(pool_info);
2333 
2334 	DBUG_RETURN(status);
2335 }
2336 
2337 /*******************************************************************//**
2338 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
2339 @return	0 on success, 1 on failure */
2340 static
2341 int
i_s_innodb_buffer_pool_stats_init(void * p)2342 i_s_innodb_buffer_pool_stats_init(
2343 /*==============================*/
2344 	void*	p)	/*!< in/out: table schema object */
2345 {
2346 	ST_SCHEMA_TABLE*	schema;
2347 
2348 	DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
2349 
2350 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
2351 
2352 	schema->fields_info = i_s_innodb_buffer_stats_fields_info;
2353 	schema->fill_table = i_s_innodb_buffer_stats_fill_table;
2354 
2355 	DBUG_RETURN(0);
2356 }
2357 
2358 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_buffer_stats =
2359 {
2360 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
2361 	/* int */
2362 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2363 
2364 	/* pointer to type-specific plugin descriptor */
2365 	/* void* */
2366 	STRUCT_FLD(info, &i_s_info),
2367 
2368 	/* plugin name */
2369 	/* const char* */
2370 	STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
2371 
2372 	/* plugin author (for SHOW PLUGINS) */
2373 	/* const char* */
2374 	STRUCT_FLD(author, plugin_author),
2375 
2376 	/* general descriptive text (for SHOW PLUGINS) */
2377 	/* const char* */
2378 	STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
2379 
2380 	/* the plugin license (PLUGIN_LICENSE_XXX) */
2381 	/* int */
2382 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2383 
2384 	/* the function to invoke when plugin is loaded */
2385 	/* int (*)(void*); */
2386 	STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
2387 
2388 	/* the function to invoke when plugin is unloaded */
2389 	/* int (*)(void*); */
2390 	STRUCT_FLD(deinit, i_s_common_deinit),
2391 
2392 	/* plugin version (for SHOW PLUGINS) */
2393 	/* unsigned int */
2394 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
2395 
2396 	/* struct st_mysql_show_var* */
2397 	STRUCT_FLD(status_vars, NULL),
2398 
2399 	/* struct st_mysql_sys_var** */
2400 	STRUCT_FLD(system_vars, NULL),
2401 
2402 	/* reserved for dependency checking */
2403 	/* void* */
2404 	STRUCT_FLD(__reserved1, NULL),
2405 
2406 	/* Plugin flags */
2407 	/* unsigned long */
2408 	STRUCT_FLD(flags, 0UL),
2409 };
2410 
2411 /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
2412 static ST_FIELD_INFO	i_s_innodb_buffer_page_fields_info[] =
2413 {
2414 #define IDX_BUFFER_POOL_ID		0
2415 	{STRUCT_FLD(field_name,		"POOL_ID"),
2416 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2417 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2418 	 STRUCT_FLD(value,		0),
2419 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2420 	 STRUCT_FLD(old_name,		""),
2421 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2422 
2423 #define IDX_BUFFER_BLOCK_ID		1
2424 	{STRUCT_FLD(field_name,		"BLOCK_ID"),
2425 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2426 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2427 	 STRUCT_FLD(value,		0),
2428 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2429 	 STRUCT_FLD(old_name,		""),
2430 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2431 
2432 #define IDX_BUFFER_PAGE_SPACE		2
2433 	{STRUCT_FLD(field_name,		"SPACE"),
2434 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2435 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2436 	 STRUCT_FLD(value,		0),
2437 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2438 	 STRUCT_FLD(old_name,		""),
2439 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2440 
2441 #define IDX_BUFFER_PAGE_NUM		3
2442 	{STRUCT_FLD(field_name,		"PAGE_NUMBER"),
2443 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2444 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2445 	 STRUCT_FLD(value,		0),
2446 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2447 	 STRUCT_FLD(old_name,		""),
2448 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2449 
2450 #define IDX_BUFFER_PAGE_TYPE		4
2451 	{STRUCT_FLD(field_name,		"PAGE_TYPE"),
2452 	 STRUCT_FLD(field_length,	64),
2453 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2454 	 STRUCT_FLD(value,		0),
2455 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2456 	 STRUCT_FLD(old_name,		""),
2457 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2458 
2459 #define IDX_BUFFER_PAGE_FLUSH_TYPE	5
2460 	{STRUCT_FLD(field_name,		"FLUSH_TYPE"),
2461 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2462 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2463 	 STRUCT_FLD(value,		0),
2464 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2465 	 STRUCT_FLD(old_name,		""),
2466 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2467 
2468 #define IDX_BUFFER_PAGE_FIX_COUNT	6
2469 	{STRUCT_FLD(field_name,		"FIX_COUNT"),
2470 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2471 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2472 	 STRUCT_FLD(value,		0),
2473 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2474 	 STRUCT_FLD(old_name,		""),
2475 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2476 
2477 #define IDX_BUFFER_PAGE_HASHED		7
2478 	{STRUCT_FLD(field_name,		"IS_HASHED"),
2479 	 STRUCT_FLD(field_length,	3),
2480 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2481 	 STRUCT_FLD(value,		0),
2482 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2483 	 STRUCT_FLD(old_name,		""),
2484 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2485 
2486 #define IDX_BUFFER_PAGE_NEWEST_MOD	8
2487 	{STRUCT_FLD(field_name,		"NEWEST_MODIFICATION"),
2488 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2489 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2490 	 STRUCT_FLD(value,		0),
2491 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2492 	 STRUCT_FLD(old_name,		""),
2493 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2494 
2495 #define IDX_BUFFER_PAGE_OLDEST_MOD	9
2496 	{STRUCT_FLD(field_name,		"OLDEST_MODIFICATION"),
2497 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2498 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2499 	 STRUCT_FLD(value,		0),
2500 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2501 	 STRUCT_FLD(old_name,		""),
2502 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2503 
2504 #define IDX_BUFFER_PAGE_ACCESS_TIME	10
2505 	{STRUCT_FLD(field_name,		"ACCESS_TIME"),
2506 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2507 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2508 	 STRUCT_FLD(value,		0),
2509 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2510 	 STRUCT_FLD(old_name,		""),
2511 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2512 
2513 #define IDX_BUFFER_PAGE_TABLE_NAME	11
2514 	{STRUCT_FLD(field_name,		"TABLE_NAME"),
2515 	 STRUCT_FLD(field_length,	1024),
2516 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2517 	 STRUCT_FLD(value,		0),
2518 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2519 	 STRUCT_FLD(old_name,		""),
2520 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2521 
2522 #define IDX_BUFFER_PAGE_INDEX_NAME	12
2523 	{STRUCT_FLD(field_name,		"INDEX_NAME"),
2524 	 STRUCT_FLD(field_length,	1024),
2525 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2526 	 STRUCT_FLD(value,		0),
2527 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2528 	 STRUCT_FLD(old_name,		""),
2529 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2530 
2531 #define IDX_BUFFER_PAGE_NUM_RECS	13
2532 	{STRUCT_FLD(field_name,		"NUMBER_RECORDS"),
2533 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2534 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2535 	 STRUCT_FLD(value,		0),
2536 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2537 	 STRUCT_FLD(old_name,		""),
2538 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2539 
2540 #define IDX_BUFFER_PAGE_DATA_SIZE	14
2541 	{STRUCT_FLD(field_name,		"DATA_SIZE"),
2542 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2543 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2544 	 STRUCT_FLD(value,		0),
2545 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2546 	 STRUCT_FLD(old_name,		""),
2547 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2548 
2549 #define IDX_BUFFER_PAGE_ZIP_SIZE	15
2550 	{STRUCT_FLD(field_name,		"COMPRESSED_SIZE"),
2551 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2552 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2553 	 STRUCT_FLD(value,		0),
2554 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2555 	 STRUCT_FLD(old_name,		""),
2556 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2557 
2558 #define IDX_BUFFER_PAGE_STATE		16
2559 	{STRUCT_FLD(field_name,		"PAGE_STATE"),
2560 	 STRUCT_FLD(field_length,	64),
2561 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2562 	 STRUCT_FLD(value,		0),
2563 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2564 	 STRUCT_FLD(old_name,		""),
2565 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2566 
2567 #define IDX_BUFFER_PAGE_IO_FIX		17
2568 	{STRUCT_FLD(field_name,		"IO_FIX"),
2569 	 STRUCT_FLD(field_length,	64),
2570 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2571 	 STRUCT_FLD(value,		0),
2572 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2573 	 STRUCT_FLD(old_name,		""),
2574 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2575 
2576 #define IDX_BUFFER_PAGE_IS_OLD		18
2577 	{STRUCT_FLD(field_name,		"IS_OLD"),
2578 	 STRUCT_FLD(field_length,	3),
2579 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2580 	 STRUCT_FLD(value,		0),
2581 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2582 	 STRUCT_FLD(old_name,		""),
2583 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2584 
2585 #define IDX_BUFFER_PAGE_FREE_CLOCK	19
2586 	{STRUCT_FLD(field_name,		"FREE_PAGE_CLOCK"),
2587 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2588 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2589 	 STRUCT_FLD(value,		0),
2590 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2591 	 STRUCT_FLD(old_name,		""),
2592 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2593 
2594 	END_OF_ST_FIELD_INFO
2595 };
2596 
2597 /*******************************************************************//**
2598 Fill Information Schema table INNODB_BUFFER_PAGE with information
2599 cached in the buf_page_info_t array
2600 @return	0 on success, 1 on failure */
2601 static
2602 int
i_s_innodb_buffer_page_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page,mem_heap_t * heap)2603 i_s_innodb_buffer_page_fill(
2604 /*========================*/
2605 	THD*			thd,		/*!< in: thread */
2606 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
2607 	const buf_page_info_t*	info_array,	/*!< in: array cached page
2608 						info */
2609 	ulint			num_page,	/*!< in: number of page info
2610 						 cached */
2611 	mem_heap_t*		heap)		/*!< in: temp heap memory */
2612 {
2613 	TABLE*			table;
2614 	Field**			fields;
2615 
2616 	DBUG_ENTER("i_s_innodb_buffer_page_fill");
2617 
2618 	table = tables->table;
2619 
2620 	fields = table->field;
2621 
2622 	/* Iterate through the cached array and fill the I_S table rows */
2623 	for (ulint i = 0; i < num_page; i++) {
2624 		const buf_page_info_t*	page_info;
2625 		const char*		table_name;
2626 		const char*		index_name;
2627 		const char*		state_str;
2628 		enum buf_page_state	state;
2629 
2630 		page_info = info_array + i;
2631 
2632 		table_name = NULL;
2633 		index_name = NULL;
2634 		state_str = NULL;
2635 
2636 		OK(fields[IDX_BUFFER_POOL_ID]->store(page_info->pool_id));
2637 
2638 		OK(fields[IDX_BUFFER_BLOCK_ID]->store(page_info->block_id));
2639 
2640 		OK(fields[IDX_BUFFER_PAGE_SPACE]->store(page_info->space_id));
2641 
2642 		OK(fields[IDX_BUFFER_PAGE_NUM]->store(page_info->page_num));
2643 
2644 		OK(field_store_string(
2645 			fields[IDX_BUFFER_PAGE_TYPE],
2646 			i_s_page_type[page_info->page_type].type_str));
2647 
2648 		OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
2649 			page_info->flush_type));
2650 
2651 		OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
2652 			page_info->fix_count));
2653 
2654 		if (page_info->hashed) {
2655 			OK(field_store_string(
2656 				fields[IDX_BUFFER_PAGE_HASHED], "YES"));
2657 		} else {
2658 			OK(field_store_string(
2659 				fields[IDX_BUFFER_PAGE_HASHED], "NO"));
2660 		}
2661 
2662 		OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
2663 			(longlong) page_info->newest_mod, true));
2664 
2665 		OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
2666 			(longlong) page_info->oldest_mod, true));
2667 
2668 		OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
2669 			page_info->access_time));
2670 
2671 		/* If this is an index page, fetch the index name
2672 		and table name */
2673 		if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
2674 			const dict_index_t*	index;
2675 
2676 			mutex_enter(&dict_sys->mutex);
2677 			index = dict_index_get_if_in_cache_low(
2678 				page_info->index_id);
2679 
2680 			/* Copy the index/table name under mutex. We
2681 			do not want to hold the InnoDB mutex while
2682 			filling the IS table */
2683 			if (index) {
2684 				const char*	name_ptr = index->name;
2685 
2686 				if (name_ptr[0] == TEMP_INDEX_PREFIX) {
2687 					name_ptr++;
2688 				}
2689 
2690 				index_name = mem_heap_strdup(heap, name_ptr);
2691 
2692 				table_name = mem_heap_strdup(heap,
2693 							     index->table_name);
2694 
2695                                 DBUG_EXECUTE_IF("mysql_test_print_index_type",
2696                                   {
2697                                     char idx_type[3];
2698 
2699                                     ut_snprintf(idx_type,
2700                                                 sizeof(idx_type),
2701                                                 "%d",
2702                                                 index->type);
2703 
2704                                     index_name=mem_heap_strcat(heap,
2705                                                                index_name,
2706                                                                idx_type);
2707                                   };);
2708 			}
2709 
2710 			mutex_exit(&dict_sys->mutex);
2711 		}
2712 
2713 		OK(field_store_string(
2714 			fields[IDX_BUFFER_PAGE_TABLE_NAME], table_name));
2715 
2716 		OK(field_store_string(
2717 			fields[IDX_BUFFER_PAGE_INDEX_NAME], index_name));
2718 
2719 		OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
2720 			page_info->num_recs));
2721 
2722 		OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
2723 			page_info->data_size));
2724 
2725 		OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
2726 			page_info->zip_ssize
2727 			? (PAGE_ZIP_MIN_SIZE >> 1) << page_info->zip_ssize
2728 			: 0));
2729 
2730 #if BUF_PAGE_STATE_BITS > 3
2731 # error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
2732 #endif
2733 		state = static_cast<enum buf_page_state>(page_info->page_state);
2734 
2735 		switch (state) {
2736 		/* First three states are for compression pages and
2737 		are not states we would get as we scan pages through
2738 		buffer blocks */
2739 		case BUF_BLOCK_ZIP_FREE:
2740 		case BUF_BLOCK_ZIP_PAGE:
2741 		case BUF_BLOCK_ZIP_DIRTY:
2742 			state_str = NULL;
2743 			break;
2744 		case BUF_BLOCK_NOT_USED:
2745 			state_str = "NOT_USED";
2746 			break;
2747 		case BUF_BLOCK_READY_FOR_USE:
2748 			state_str = "READY_FOR_USE";
2749 			break;
2750 		case BUF_BLOCK_FILE_PAGE:
2751 			state_str = "FILE_PAGE";
2752 			break;
2753 		case BUF_BLOCK_MEMORY:
2754 			state_str = "MEMORY";
2755 			break;
2756 		case BUF_BLOCK_REMOVE_HASH:
2757 			state_str = "REMOVE_HASH";
2758 			break;
2759 		};
2760 
2761 		OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
2762 				      state_str));
2763 
2764 		switch (page_info->io_fix) {
2765 		case BUF_IO_NONE:
2766 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
2767 					      "IO_NONE"));
2768 			break;
2769 		case BUF_IO_READ:
2770 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
2771 					      "IO_READ"));
2772 			break;
2773 		case BUF_IO_WRITE:
2774 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
2775 					      "IO_WRITE"));
2776 			break;
2777 		case BUF_IO_PIN:
2778 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
2779 					      "IO_PIN"));
2780 			break;
2781 		}
2782 
2783 		OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
2784 				      (page_info->is_old) ? "YES" : "NO"));
2785 
2786 		OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
2787 			page_info->freed_page_clock));
2788 
2789 		if (schema_table_store_record(thd, table)) {
2790 			DBUG_RETURN(1);
2791 		}
2792 	}
2793 
2794 	DBUG_RETURN(0);
2795 }
2796 
2797 /*******************************************************************//**
2798 Set appropriate page type to a buf_page_info_t structure */
2799 static
2800 void
i_s_innodb_set_page_type(buf_page_info_t * page_info,ulint page_type,const byte * frame)2801 i_s_innodb_set_page_type(
2802 /*=====================*/
2803 	buf_page_info_t*page_info,	/*!< in/out: structure to fill with
2804 					scanned info */
2805 	ulint		page_type,	/*!< in: page type */
2806 	const byte*	frame)		/*!< in: buffer frame */
2807 {
2808 	if (page_type == FIL_PAGE_INDEX) {
2809 		const page_t*	page = (const page_t*) frame;
2810 
2811 		page_info->index_id = btr_page_get_index_id(page);
2812 
2813 		/* FIL_PAGE_INDEX is a bit special, its value
2814 		is defined as 17855, so we cannot use FIL_PAGE_INDEX
2815 		to index into i_s_page_type[] array, its array index
2816 		in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
2817 		(1) for index pages or I_S_PAGE_TYPE_IBUF for
2818 		change buffer index pages */
2819 		if (page_info->index_id
2820 		    == static_cast<index_id_t>(DICT_IBUF_ID_MIN
2821 					       + IBUF_SPACE_ID)) {
2822 			page_info->page_type = I_S_PAGE_TYPE_IBUF;
2823 		} else {
2824 			page_info->page_type = I_S_PAGE_TYPE_INDEX;
2825 		}
2826 
2827 		page_info->data_size = (ulint)(page_header_get_field(
2828 			page, PAGE_HEAP_TOP) - (page_is_comp(page)
2829 						? PAGE_NEW_SUPREMUM_END
2830 						: PAGE_OLD_SUPREMUM_END)
2831 			- page_header_get_field(page, PAGE_GARBAGE));
2832 
2833 		page_info->num_recs = page_get_n_recs(page);
2834 	} else if (page_type > FIL_PAGE_TYPE_LAST) {
2835 		/* Encountered an unknown page type */
2836 		page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
2837 	} else {
2838 		/* Make sure we get the right index into the
2839 		i_s_page_type[] array */
2840 		ut_a(page_type == i_s_page_type[page_type].type_value);
2841 
2842 		page_info->page_type = page_type;
2843 	}
2844 
2845 	if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
2846 	    || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
2847 		page_info->page_num = mach_read_from_4(
2848 			frame + FIL_PAGE_OFFSET);
2849 		page_info->space_id = mach_read_from_4(
2850 			frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
2851 	}
2852 }
2853 /*******************************************************************//**
2854 Scans pages in the buffer cache, and collect their general information
2855 into the buf_page_info_t array which is zero-filled. So any fields
2856 that are not initialized in the function will default to 0 */
2857 static
2858 void
i_s_innodb_buffer_page_get_info(const buf_page_t * bpage,ulint pool_id,ulint pos,buf_page_info_t * page_info)2859 i_s_innodb_buffer_page_get_info(
2860 /*============================*/
2861 	const buf_page_t*bpage,		/*!< in: buffer pool page to scan */
2862 	ulint		pool_id,	/*!< in: buffer pool id */
2863 	ulint		pos,		/*!< in: buffer block position in
2864 					buffer pool or in the LRU list */
2865 	buf_page_info_t*page_info)	/*!< in: zero filled info structure;
2866 					out: structure filled with scanned
2867 					info */
2868 {
2869 	ut_ad(pool_id < MAX_BUFFER_POOLS);
2870 
2871 	page_info->pool_id = pool_id;
2872 
2873 	page_info->block_id = pos;
2874 
2875 	page_info->page_state = buf_page_get_state(bpage);
2876 
2877 	/* Only fetch information for buffers that map to a tablespace,
2878 	that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
2879 	BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
2880 	if (buf_page_in_file(bpage)) {
2881 		const byte*	frame;
2882 		ulint		page_type;
2883 
2884 		page_info->space_id = buf_page_get_space(bpage);
2885 
2886 		page_info->page_num = buf_page_get_page_no(bpage);
2887 
2888 		page_info->flush_type = bpage->flush_type;
2889 
2890 		page_info->fix_count = bpage->buf_fix_count;
2891 
2892 		page_info->newest_mod = bpage->newest_modification;
2893 
2894 		page_info->oldest_mod = bpage->oldest_modification;
2895 
2896 		page_info->access_time = bpage->access_time;
2897 
2898 		page_info->zip_ssize = bpage->zip.ssize;
2899 
2900 		page_info->io_fix = bpage->io_fix;
2901 
2902 		page_info->is_old = bpage->old;
2903 
2904 		page_info->freed_page_clock = bpage->freed_page_clock;
2905 
2906 		switch (buf_page_get_io_fix(bpage)) {
2907 		case BUF_IO_NONE:
2908 		case BUF_IO_WRITE:
2909 		case BUF_IO_PIN:
2910 			break;
2911 		case BUF_IO_READ:
2912 			page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
2913 			return;
2914 		}
2915 
2916 		if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
2917 			const buf_block_t*block;
2918 
2919 			block = reinterpret_cast<const buf_block_t*>(bpage);
2920 			frame = block->frame;
2921 			page_info->hashed = (block->index != NULL);
2922 		} else {
2923 			ut_ad(page_info->zip_ssize);
2924 			frame = bpage->zip.data;
2925 		}
2926 
2927 		page_type = fil_page_get_type(frame);
2928 
2929 		i_s_innodb_set_page_type(page_info, page_type, frame);
2930 	} else {
2931 		page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
2932 	}
2933 }
2934 
2935 /*******************************************************************//**
2936 This is the function that goes through each block of the buffer pool
2937 and fetch information to information schema tables: INNODB_BUFFER_PAGE.
2938 @return	0 on success, 1 on failure */
2939 static
2940 int
i_s_innodb_fill_buffer_pool(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)2941 i_s_innodb_fill_buffer_pool(
2942 /*========================*/
2943 	THD*			thd,		/*!< in: thread */
2944 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
2945 	buf_pool_t*		buf_pool,	/*!< in: buffer pool to scan */
2946 	const ulint		pool_id)	/*!< in: buffer pool id */
2947 {
2948 	int			status	= 0;
2949 	mem_heap_t*		heap;
2950 
2951 	DBUG_ENTER("i_s_innodb_fill_buffer_pool");
2952 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
2953 
2954 	heap = mem_heap_create(10000);
2955 
2956 	/* Go through each chunk of buffer pool. Currently, we only
2957 	have one single chunk for each buffer pool */
2958 	for (ulint n = 0; n < buf_pool->n_chunks; n++) {
2959 		const buf_block_t*	block;
2960 		ulint			n_blocks;
2961 		buf_page_info_t*	info_buffer;
2962 		ulint			num_page;
2963 		ulint			mem_size;
2964 		ulint			chunk_size;
2965 		ulint			num_to_process = 0;
2966 		ulint			block_id = 0;
2967 
2968 		/* Get buffer block of the nth chunk */
2969 		block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
2970 		num_page = 0;
2971 
2972 		while (chunk_size > 0) {
2973 			/* we cache maximum MAX_BUF_INFO_CACHED number of
2974 			buffer page info */
2975 			num_to_process = ut_min(chunk_size,
2976 						MAX_BUF_INFO_CACHED);
2977 
2978 			mem_size = num_to_process * sizeof(buf_page_info_t);
2979 
2980 			/* For each chunk, we'll pre-allocate information
2981 			structures to cache the page information read from
2982 			the buffer pool. Doing so before obtain any mutex */
2983 			info_buffer = (buf_page_info_t*) mem_heap_zalloc(
2984 				heap, mem_size);
2985 
2986 			/* Obtain appropriate mutexes. Since this is diagnostic
2987 			buffer pool info printout, we are not required to
2988 			preserve the overall consistency, so we can
2989 			release mutex periodically */
2990 			buf_pool_mutex_enter(buf_pool);
2991 
2992 			/* GO through each block in the chunk */
2993 			for (n_blocks = num_to_process; n_blocks--; block++) {
2994 				i_s_innodb_buffer_page_get_info(
2995 					&block->page, pool_id, block_id,
2996 					info_buffer + num_page);
2997 				block_id++;
2998 				num_page++;
2999 			}
3000 
3001 			buf_pool_mutex_exit(buf_pool);
3002 
3003 			/* Fill in information schema table with information
3004 			just collected from the buffer chunk scan */
3005 			status = i_s_innodb_buffer_page_fill(
3006 				thd, tables, info_buffer,
3007 				num_page, heap);
3008 
3009 			/* If something goes wrong, break and return */
3010 			if (status) {
3011 				break;
3012 			}
3013 
3014 			mem_heap_empty(heap);
3015 			chunk_size -= num_to_process;
3016 			num_page = 0;
3017 		}
3018 	}
3019 
3020 	mem_heap_free(heap);
3021 
3022 	DBUG_RETURN(status);
3023 }
3024 
3025 /*******************************************************************//**
3026 Fill page information for pages in InnoDB buffer pool to the
3027 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
3028 @return	0 on success, 1 on failure */
3029 static
3030 int
i_s_innodb_buffer_page_fill_table(THD * thd,TABLE_LIST * tables,Item *)3031 i_s_innodb_buffer_page_fill_table(
3032 /*==============================*/
3033 	THD*		thd,		/*!< in: thread */
3034 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
3035 	Item*		)		/*!< in: condition (ignored) */
3036 {
3037 	int	status	= 0;
3038 
3039 	DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
3040 
3041 	/* deny access to user without PROCESS privilege */
3042 	if (check_global_access(thd, PROCESS_ACL)) {
3043 		DBUG_RETURN(0);
3044 	}
3045 
3046 	/* Walk through each buffer pool */
3047 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
3048 		buf_pool_t*	buf_pool;
3049 
3050 		buf_pool = buf_pool_from_array(i);
3051 
3052 		/* Fetch information from pages in this buffer pool,
3053 		and fill the corresponding I_S table */
3054 		status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
3055 
3056 		/* If something wrong, break and return */
3057 		if (status) {
3058 			break;
3059 		}
3060 	}
3061 
3062 	DBUG_RETURN(status);
3063 }
3064 
3065 /*******************************************************************//**
3066 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
3067 @return	0 on success, 1 on failure */
3068 static
3069 int
i_s_innodb_buffer_page_init(void * p)3070 i_s_innodb_buffer_page_init(
3071 /*========================*/
3072 	void*	p)	/*!< in/out: table schema object */
3073 {
3074 	ST_SCHEMA_TABLE*	schema;
3075 
3076 	DBUG_ENTER("i_s_innodb_buffer_page_init");
3077 
3078 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
3079 
3080 	schema->fields_info = i_s_innodb_buffer_page_fields_info;
3081 	schema->fill_table = i_s_innodb_buffer_page_fill_table;
3082 
3083 	DBUG_RETURN(0);
3084 }
3085 
3086 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_buffer_page =
3087 {
3088 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3089 	/* int */
3090 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3091 
3092 	/* pointer to type-specific plugin descriptor */
3093 	/* void* */
3094 	STRUCT_FLD(info, &i_s_info),
3095 
3096 	/* plugin name */
3097 	/* const char* */
3098 	STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
3099 
3100 	/* plugin author (for SHOW PLUGINS) */
3101 	/* const char* */
3102 	STRUCT_FLD(author, plugin_author),
3103 
3104 	/* general descriptive text (for SHOW PLUGINS) */
3105 	/* const char* */
3106 	STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
3107 
3108 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3109 	/* int */
3110 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3111 
3112 	/* the function to invoke when plugin is loaded */
3113 	/* int (*)(void*); */
3114 	STRUCT_FLD(init, i_s_innodb_buffer_page_init),
3115 
3116 	/* the function to invoke when plugin is unloaded */
3117 	/* int (*)(void*); */
3118 	STRUCT_FLD(deinit, i_s_common_deinit),
3119 
3120 	/* plugin version (for SHOW PLUGINS) */
3121 	/* unsigned int */
3122 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
3123 
3124 	/* struct st_mysql_show_var* */
3125 	STRUCT_FLD(status_vars, NULL),
3126 
3127 	/* struct st_mysql_sys_var** */
3128 	STRUCT_FLD(system_vars, NULL),
3129 
3130 	/* reserved for dependency checking */
3131 	/* void* */
3132 	STRUCT_FLD(__reserved1, NULL),
3133 
3134 	/* Plugin flags */
3135 	/* unsigned long */
3136 	STRUCT_FLD(flags, 0UL),
3137 };
3138 
3139 static ST_FIELD_INFO	i_s_innodb_buf_page_lru_fields_info[] =
3140 {
3141 #define IDX_BUF_LRU_POOL_ID		0
3142 	{STRUCT_FLD(field_name,		"POOL_ID"),
3143 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3144 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3145 	 STRUCT_FLD(value,		0),
3146 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3147 	 STRUCT_FLD(old_name,		""),
3148 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3149 
3150 #define IDX_BUF_LRU_POS			1
3151 	{STRUCT_FLD(field_name,		"LRU_POSITION"),
3152 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3153 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3154 	 STRUCT_FLD(value,		0),
3155 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3156 	 STRUCT_FLD(old_name,		""),
3157 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3158 
3159 #define IDX_BUF_LRU_PAGE_SPACE		2
3160 	{STRUCT_FLD(field_name,		"SPACE"),
3161 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3162 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3163 	 STRUCT_FLD(value,		0),
3164 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3165 	 STRUCT_FLD(old_name,		""),
3166 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3167 
3168 #define IDX_BUF_LRU_PAGE_NUM		3
3169 	{STRUCT_FLD(field_name,		"PAGE_NUMBER"),
3170 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3171 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3172 	 STRUCT_FLD(value,		0),
3173 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3174 	 STRUCT_FLD(old_name,		""),
3175 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3176 
3177 #define IDX_BUF_LRU_PAGE_TYPE		4
3178 	{STRUCT_FLD(field_name,		"PAGE_TYPE"),
3179 	 STRUCT_FLD(field_length,	64),
3180 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3181 	 STRUCT_FLD(value,		0),
3182 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
3183 	 STRUCT_FLD(old_name,		""),
3184 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3185 
3186 #define IDX_BUF_LRU_PAGE_FLUSH_TYPE	5
3187 	{STRUCT_FLD(field_name,		"FLUSH_TYPE"),
3188 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3189 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3190 	 STRUCT_FLD(value,		0),
3191 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3192 	 STRUCT_FLD(old_name,		""),
3193 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3194 
3195 #define IDX_BUF_LRU_PAGE_FIX_COUNT	6
3196 	{STRUCT_FLD(field_name,		"FIX_COUNT"),
3197 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3198 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3199 	 STRUCT_FLD(value,		0),
3200 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3201 	 STRUCT_FLD(old_name,		""),
3202 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3203 
3204 #define IDX_BUF_LRU_PAGE_HASHED		7
3205 	{STRUCT_FLD(field_name,		"IS_HASHED"),
3206 	 STRUCT_FLD(field_length,	3),
3207 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3208 	 STRUCT_FLD(value,		0),
3209 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
3210 	 STRUCT_FLD(old_name,		""),
3211 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3212 
3213 #define IDX_BUF_LRU_PAGE_NEWEST_MOD	8
3214 	{STRUCT_FLD(field_name,		"NEWEST_MODIFICATION"),
3215 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3216 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3217 	 STRUCT_FLD(value,		0),
3218 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3219 	 STRUCT_FLD(old_name,		""),
3220 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3221 
3222 #define IDX_BUF_LRU_PAGE_OLDEST_MOD	9
3223 	{STRUCT_FLD(field_name,		"OLDEST_MODIFICATION"),
3224 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3225 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3226 	 STRUCT_FLD(value,		0),
3227 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3228 	 STRUCT_FLD(old_name,		""),
3229 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3230 
3231 #define IDX_BUF_LRU_PAGE_ACCESS_TIME	10
3232 	{STRUCT_FLD(field_name,		"ACCESS_TIME"),
3233 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3234 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3235 	 STRUCT_FLD(value,		0),
3236 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3237 	 STRUCT_FLD(old_name,		""),
3238 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3239 
3240 #define IDX_BUF_LRU_PAGE_TABLE_NAME	11
3241 	{STRUCT_FLD(field_name,		"TABLE_NAME"),
3242 	 STRUCT_FLD(field_length,	1024),
3243 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3244 	 STRUCT_FLD(value,		0),
3245 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
3246 	 STRUCT_FLD(old_name,		""),
3247 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3248 
3249 #define IDX_BUF_LRU_PAGE_INDEX_NAME	12
3250 	{STRUCT_FLD(field_name,		"INDEX_NAME"),
3251 	 STRUCT_FLD(field_length,	1024),
3252 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3253 	 STRUCT_FLD(value,		0),
3254 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
3255 	 STRUCT_FLD(old_name,		""),
3256 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3257 
3258 #define IDX_BUF_LRU_PAGE_NUM_RECS	13
3259 	{STRUCT_FLD(field_name,		"NUMBER_RECORDS"),
3260 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3261 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3262 	 STRUCT_FLD(value,		0),
3263 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3264 	 STRUCT_FLD(old_name,		""),
3265 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3266 
3267 #define IDX_BUF_LRU_PAGE_DATA_SIZE	14
3268 	{STRUCT_FLD(field_name,		"DATA_SIZE"),
3269 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3270 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3271 	 STRUCT_FLD(value,		0),
3272 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3273 	 STRUCT_FLD(old_name,		""),
3274 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3275 
3276 #define IDX_BUF_LRU_PAGE_ZIP_SIZE	15
3277 	{STRUCT_FLD(field_name,		"COMPRESSED_SIZE"),
3278 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3279 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3280 	 STRUCT_FLD(value,		0),
3281 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3282 	 STRUCT_FLD(old_name,		""),
3283 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3284 
3285 #define IDX_BUF_LRU_PAGE_STATE		16
3286 	{STRUCT_FLD(field_name,		"COMPRESSED"),
3287 	 STRUCT_FLD(field_length,	3),
3288 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3289 	 STRUCT_FLD(value,		0),
3290 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
3291 	 STRUCT_FLD(old_name,		""),
3292 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3293 
3294 #define IDX_BUF_LRU_PAGE_IO_FIX		17
3295 	{STRUCT_FLD(field_name,		"IO_FIX"),
3296 	 STRUCT_FLD(field_length,	64),
3297 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3298 	 STRUCT_FLD(value,		0),
3299 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
3300 	 STRUCT_FLD(old_name,		""),
3301 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3302 
3303 #define IDX_BUF_LRU_PAGE_IS_OLD		18
3304 	{STRUCT_FLD(field_name,		"IS_OLD"),
3305 	 STRUCT_FLD(field_length,	3),
3306 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3307 	 STRUCT_FLD(value,		0),
3308 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
3309 	 STRUCT_FLD(old_name,		""),
3310 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3311 
3312 #define IDX_BUF_LRU_PAGE_FREE_CLOCK	19
3313 	{STRUCT_FLD(field_name,		"FREE_PAGE_CLOCK"),
3314 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3315 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3316 	 STRUCT_FLD(value,		0),
3317 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3318 	 STRUCT_FLD(old_name,		""),
3319 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3320 
3321 	END_OF_ST_FIELD_INFO
3322 };
3323 
3324 /*******************************************************************//**
3325 Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
3326 cached in the buf_page_info_t array
3327 @return	0 on success, 1 on failure */
3328 static
3329 int
i_s_innodb_buf_page_lru_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)3330 i_s_innodb_buf_page_lru_fill(
3331 /*=========================*/
3332 	THD*			thd,		/*!< in: thread */
3333 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
3334 	const buf_page_info_t*	info_array,	/*!< in: array cached page
3335 						info */
3336 	ulint			num_page)	/*!< in: number of page info
3337 						 cached */
3338 {
3339 	TABLE*			table;
3340 	Field**			fields;
3341 	mem_heap_t*		heap;
3342 
3343 	DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
3344 
3345 	table = tables->table;
3346 
3347 	fields = table->field;
3348 
3349 	heap = mem_heap_create(1000);
3350 
3351 	/* Iterate through the cached array and fill the I_S table rows */
3352 	for (ulint i = 0; i < num_page; i++) {
3353 		const buf_page_info_t*	page_info;
3354 		const char*		table_name;
3355 		const char*		index_name;
3356 		const char*		state_str;
3357 		enum buf_page_state	state;
3358 
3359 		table_name = NULL;
3360 		index_name = NULL;
3361 		state_str = NULL;
3362 
3363 		page_info = info_array + i;
3364 
3365 		OK(fields[IDX_BUF_LRU_POOL_ID]->store(page_info->pool_id));
3366 
3367 		OK(fields[IDX_BUF_LRU_POS]->store(page_info->block_id));
3368 
3369 		OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(page_info->space_id));
3370 
3371 		OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(page_info->page_num));
3372 
3373 		OK(field_store_string(
3374 			fields[IDX_BUF_LRU_PAGE_TYPE],
3375 			i_s_page_type[page_info->page_type].type_str));
3376 
3377 		OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
3378 			page_info->flush_type));
3379 
3380 		OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
3381 			page_info->fix_count));
3382 
3383 		if (page_info->hashed) {
3384 			OK(field_store_string(
3385 				fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
3386 		} else {
3387 			OK(field_store_string(
3388 				fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
3389 		}
3390 
3391 		OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
3392 			page_info->newest_mod, true));
3393 
3394 		OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
3395 			page_info->oldest_mod, true));
3396 
3397 		OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
3398 			page_info->access_time));
3399 
3400 		/* If this is an index page, fetch the index name
3401 		and table name */
3402 		if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
3403 			const dict_index_t*	index;
3404 
3405 			mutex_enter(&dict_sys->mutex);
3406 			index = dict_index_get_if_in_cache_low(
3407 				page_info->index_id);
3408 
3409 			/* Copy the index/table name under mutex. We
3410 			do not want to hold the InnoDB mutex while
3411 			filling the IS table */
3412 			if (index) {
3413 				const char*	name_ptr = index->name;
3414 
3415 				if (name_ptr[0] == TEMP_INDEX_PREFIX) {
3416 					name_ptr++;
3417 				}
3418 
3419 				index_name = mem_heap_strdup(heap, name_ptr);
3420 
3421 				table_name = mem_heap_strdup(heap,
3422 							     index->table_name);
3423 			}
3424 
3425 			mutex_exit(&dict_sys->mutex);
3426 		}
3427 
3428 		OK(field_store_string(
3429 			fields[IDX_BUF_LRU_PAGE_TABLE_NAME], table_name));
3430 
3431 		OK(field_store_string(
3432 			fields[IDX_BUF_LRU_PAGE_INDEX_NAME], index_name));
3433 		OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
3434 			page_info->num_recs));
3435 
3436 		OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
3437 			page_info->data_size));
3438 
3439 		OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
3440 			page_info->zip_ssize ?
3441 				 512 << page_info->zip_ssize : 0));
3442 
3443 		state = static_cast<enum buf_page_state>(page_info->page_state);
3444 
3445 		switch (state) {
3446 		/* Compressed page */
3447 		case BUF_BLOCK_ZIP_PAGE:
3448 		case BUF_BLOCK_ZIP_DIRTY:
3449 			state_str = "YES";
3450 			break;
3451 		/* Uncompressed page */
3452 		case BUF_BLOCK_FILE_PAGE:
3453 			state_str = "NO";
3454 			break;
3455 		/* We should not see following states */
3456 		case BUF_BLOCK_ZIP_FREE:
3457 		case BUF_BLOCK_READY_FOR_USE:
3458 		case BUF_BLOCK_NOT_USED:
3459 		case BUF_BLOCK_MEMORY:
3460 		case BUF_BLOCK_REMOVE_HASH:
3461 			state_str = NULL;
3462 			break;
3463 		};
3464 
3465 		OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
3466 				      state_str));
3467 
3468 		switch (page_info->io_fix) {
3469 		case BUF_IO_NONE:
3470 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
3471 					      "IO_NONE"));
3472 			break;
3473 		case BUF_IO_READ:
3474 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
3475 					      "IO_READ"));
3476 			break;
3477 		case BUF_IO_WRITE:
3478 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
3479 					      "IO_WRITE"));
3480 			break;
3481 		}
3482 
3483 		OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
3484 				      (page_info->is_old) ? "YES" : "NO"));
3485 
3486 		OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
3487 			page_info->freed_page_clock));
3488 
3489 		if (schema_table_store_record(thd, table)) {
3490 			mem_heap_free(heap);
3491 			DBUG_RETURN(1);
3492 		}
3493 
3494 		mem_heap_empty(heap);
3495 	}
3496 
3497 	mem_heap_free(heap);
3498 
3499 	DBUG_RETURN(0);
3500 }
3501 
3502 /*******************************************************************//**
3503 This is the function that goes through buffer pool's LRU list
3504 and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
3505 @return	0 on success, 1 on failure */
3506 static
3507 int
i_s_innodb_fill_buffer_lru(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)3508 i_s_innodb_fill_buffer_lru(
3509 /*=======================*/
3510 	THD*			thd,		/*!< in: thread */
3511 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
3512 	buf_pool_t*		buf_pool,	/*!< in: buffer pool to scan */
3513 	const ulint		pool_id)	/*!< in: buffer pool id */
3514 {
3515 	int			status = 0;
3516 	buf_page_info_t*	info_buffer;
3517 	ulint			lru_pos = 0;
3518 	const buf_page_t*	bpage;
3519 	ulint			lru_len;
3520 
3521 	DBUG_ENTER("i_s_innodb_fill_buffer_lru");
3522 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
3523 
3524 	/* Obtain buf_pool mutex before allocate info_buffer, since
3525 	UT_LIST_GET_LEN(buf_pool->LRU) could change */
3526 	buf_pool_mutex_enter(buf_pool);
3527 
3528 	lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
3529 
3530 	/* Print error message if malloc fail */
3531 	info_buffer = (buf_page_info_t*) my_malloc(
3532 		lru_len * sizeof *info_buffer, MYF(MY_WME));
3533 
3534 	if (!info_buffer) {
3535 		status = 1;
3536 		goto exit;
3537 	}
3538 
3539 	memset(info_buffer, 0, lru_len * sizeof *info_buffer);
3540 
3541 	/* Walk through Pool's LRU list and print the buffer page
3542 	information */
3543 	bpage = UT_LIST_GET_LAST(buf_pool->LRU);
3544 
3545 	while (bpage != NULL) {
3546 		/* Use the same function that collect buffer info for
3547 		INNODB_BUFFER_PAGE to get buffer page info */
3548 		i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
3549 						(info_buffer + lru_pos));
3550 
3551 		bpage = UT_LIST_GET_PREV(LRU, bpage);
3552 
3553 		lru_pos++;
3554 	}
3555 
3556 	ut_ad(lru_pos == lru_len);
3557 	ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
3558 
3559 exit:
3560 	buf_pool_mutex_exit(buf_pool);
3561 
3562 	if (info_buffer) {
3563 		status = i_s_innodb_buf_page_lru_fill(
3564 			thd, tables, info_buffer, lru_len);
3565 
3566 		my_free(info_buffer);
3567 	}
3568 
3569 	DBUG_RETURN(status);
3570 }
3571 
3572 /*******************************************************************//**
3573 Fill page information for pages in InnoDB buffer pool to the
3574 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
3575 @return	0 on success, 1 on failure */
3576 static
3577 int
i_s_innodb_buf_page_lru_fill_table(THD * thd,TABLE_LIST * tables,Item *)3578 i_s_innodb_buf_page_lru_fill_table(
3579 /*===============================*/
3580 	THD*		thd,		/*!< in: thread */
3581 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
3582 	Item*		)		/*!< in: condition (ignored) */
3583 {
3584 	int	status	= 0;
3585 
3586 	DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
3587 
3588 	/* deny access to any users that do not hold PROCESS_ACL */
3589 	if (check_global_access(thd, PROCESS_ACL)) {
3590 		DBUG_RETURN(0);
3591 	}
3592 
3593 	/* Walk through each buffer pool */
3594 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
3595 		buf_pool_t*	buf_pool;
3596 
3597 		buf_pool = buf_pool_from_array(i);
3598 
3599 		/* Fetch information from pages in this buffer pool's LRU list,
3600 		and fill the corresponding I_S table */
3601 		status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
3602 
3603 		/* If something wrong, break and return */
3604 		if (status) {
3605 			break;
3606 		}
3607 	}
3608 
3609 	DBUG_RETURN(status);
3610 }
3611 
3612 /*******************************************************************//**
3613 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
3614 @return	0 on success, 1 on failure */
3615 static
3616 int
i_s_innodb_buffer_page_lru_init(void * p)3617 i_s_innodb_buffer_page_lru_init(
3618 /*============================*/
3619 	void*	p)	/*!< in/out: table schema object */
3620 {
3621 	ST_SCHEMA_TABLE*	schema;
3622 
3623 	DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
3624 
3625 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
3626 
3627 	schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
3628 	schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
3629 
3630 	DBUG_RETURN(0);
3631 }
3632 
3633 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_buffer_page_lru =
3634 {
3635 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3636 	/* int */
3637 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3638 
3639 	/* pointer to type-specific plugin descriptor */
3640 	/* void* */
3641 	STRUCT_FLD(info, &i_s_info),
3642 
3643 	/* plugin name */
3644 	/* const char* */
3645 	STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
3646 
3647 	/* plugin author (for SHOW PLUGINS) */
3648 	/* const char* */
3649 	STRUCT_FLD(author, plugin_author),
3650 
3651 	/* general descriptive text (for SHOW PLUGINS) */
3652 	/* const char* */
3653 	STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
3654 
3655 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3656 	/* int */
3657 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3658 
3659 	/* the function to invoke when plugin is loaded */
3660 	/* int (*)(void*); */
3661 	STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
3662 
3663 	/* the function to invoke when plugin is unloaded */
3664 	/* int (*)(void*); */
3665 	STRUCT_FLD(deinit, i_s_common_deinit),
3666 
3667 	/* plugin version (for SHOW PLUGINS) */
3668 	/* unsigned int */
3669 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
3670 
3671 	/* struct st_mysql_show_var* */
3672 	STRUCT_FLD(status_vars, NULL),
3673 
3674 	/* struct st_mysql_sys_var** */
3675 	STRUCT_FLD(system_vars, NULL),
3676 
3677 	/* reserved for dependency checking */
3678 	/* void* */
3679 	STRUCT_FLD(__reserved1, NULL),
3680 
3681 	/* Plugin flags */
3682 	/* unsigned long */
3683 	STRUCT_FLD(flags, 0UL),
3684 };
3685 
3686 /*******************************************************************//**
3687 Unbind a dynamic INFORMATION_SCHEMA table.
3688 @return	0 on success */
3689 static
3690 int
i_s_common_deinit(void * p)3691 i_s_common_deinit(
3692 /*==============*/
3693 	void*	p)	/*!< in/out: table schema object */
3694 {
3695 	DBUG_ENTER("i_s_common_deinit");
3696 
3697 	/* Do nothing */
3698 
3699 	DBUG_RETURN(0);
3700 }
3701 
3702 
3703