1 /*****************************************************************************
2 
3 Copyright (c) 2007, 2020, Oracle and/or its affiliates.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file handler/i_s.cc
29 InnoDB INFORMATION SCHEMA tables interface to MySQL.
30 
31 Created July 18, 2007 Vasil Dimov
32 *******************************************************/
33 
34 #include <mysqld_error.h>
35 #include <sql_acl.h>
36 
37 #include <m_ctype.h>
38 #include <hash.h>
39 #include <myisampack.h>
40 #include <mysys_err.h>
41 #include <my_sys.h>
42 #include "i_s.h"
43 #include <sql_plugin.h>
44 #include <mysql/innodb_priv.h>
45 
46 #include "btr0pcur.h"
47 #include "btr0types.h"
48 #include "dict0dict.h"
49 #include "dict0load.h"
50 #include "buf0buddy.h"
51 #include "buf0buf.h"
52 #include "ibuf0ibuf.h"
53 #include "dict0mem.h"
54 #include "dict0types.h"
55 #include "ha_prototypes.h"
56 #include "srv0start.h"
57 #include "trx0i_s.h"
58 #include "trx0trx.h"
59 #include "srv0mon.h"
60 #include "fut0fut.h"
61 #include "pars0pars.h"
62 #include "fts0types.h"
63 #include "fts0opt.h"
64 #include "fts0priv.h"
65 #include "btr0btr.h"
66 #include "page0zip.h"
67 
68 #include <string>
69 
70 /** structure associates a name string with a file page type and/or buffer
71 page state. */
72 struct buf_page_desc_t{
73 	const char*	type_str;	/*!< String explain the page
74 					type/state */
75 	ulint		type_value;	/*!< Page type or page state */
76 };
77 
78 /** Change buffer B-tree page */
79 #define	I_S_PAGE_TYPE_IBUF		(FIL_PAGE_TYPE_LAST + 1)
80 
81 /** Any states greater than I_S_PAGE_TYPE_IBUF would be treated as
82 unknown. */
83 #define	I_S_PAGE_TYPE_UNKNOWN		(I_S_PAGE_TYPE_IBUF + 1)
84 
85 /** We also define I_S_PAGE_TYPE_INDEX as the Index Page's position
86 in i_s_page_type[] array */
87 #define I_S_PAGE_TYPE_INDEX		1
88 
89 /** Name string for File Page Types */
90 static buf_page_desc_t	i_s_page_type[] = {
91 	{"ALLOCATED", FIL_PAGE_TYPE_ALLOCATED},
92 	{"INDEX", FIL_PAGE_INDEX},
93 	{"UNDO_LOG", FIL_PAGE_UNDO_LOG},
94 	{"INODE", FIL_PAGE_INODE},
95 	{"IBUF_FREE_LIST", FIL_PAGE_IBUF_FREE_LIST},
96 	{"IBUF_BITMAP", FIL_PAGE_IBUF_BITMAP},
97 	{"SYSTEM", FIL_PAGE_TYPE_SYS},
98 	{"TRX_SYSTEM", FIL_PAGE_TYPE_TRX_SYS},
99 	{"FILE_SPACE_HEADER", FIL_PAGE_TYPE_FSP_HDR},
100 	{"EXTENT_DESCRIPTOR", FIL_PAGE_TYPE_XDES},
101 	{"BLOB", FIL_PAGE_TYPE_BLOB},
102 	{"COMPRESSED_BLOB", FIL_PAGE_TYPE_ZBLOB},
103 	{"COMPRESSED_BLOB2", FIL_PAGE_TYPE_ZBLOB2},
104 	{"IBUF_INDEX", I_S_PAGE_TYPE_IBUF},
105 	{"UNKNOWN", I_S_PAGE_TYPE_UNKNOWN}
106 };
107 
108 /* Check if we can hold all page type in a 4 bit value */
109 #if I_S_PAGE_TYPE_UNKNOWN > 1<<4
110 # error "i_s_page_type[] is too large"
111 #endif
112 
113 /** This structure defines information we will fetch from pages
114 currently cached in the buffer pool. It will be used to populate
115 table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE */
116 struct buf_page_info_t{
117 	ulint		block_id;	/*!< Buffer Pool block ID */
118 	unsigned	space_id:32;	/*!< Tablespace ID */
119 	unsigned	page_num:32;	/*!< Page number/offset */
120 	unsigned	access_time:32;	/*!< Time of first access */
121 	unsigned	pool_id:MAX_BUFFER_POOLS_BITS;
122 					/*!< Buffer Pool ID. Must be less than
123 					MAX_BUFFER_POOLS */
124 	unsigned	flush_type:2;	/*!< Flush type */
125 	unsigned	io_fix:2;	/*!< type of pending I/O operation */
126 	unsigned	fix_count:19;	/*!< Count of how manyfold this block
127 					is bufferfixed */
128 	unsigned	hashed:1;	/*!< Whether hash index has been
129 					built on this page */
130 	unsigned	is_old:1;	/*!< TRUE if the block is in the old
131 					blocks in buf_pool->LRU_old */
132 	unsigned	freed_page_clock:31; /*!< the value of
133 					buf_pool->freed_page_clock */
134 	unsigned	zip_ssize:PAGE_ZIP_SSIZE_BITS;
135 					/*!< Compressed page size */
136 	unsigned	page_state:BUF_PAGE_STATE_BITS; /*!< Page state */
137 	unsigned	page_type:4;	/*!< Page type */
138 	unsigned	num_recs:UNIV_PAGE_SIZE_SHIFT_MAX-2;
139 					/*!< Number of records on Page */
140 	unsigned	data_size:UNIV_PAGE_SIZE_SHIFT_MAX;
141 					/*!< Sum of the sizes of the records */
142 	lsn_t		newest_mod;	/*!< Log sequence number of
143 					the youngest modification */
144 	lsn_t		oldest_mod;	/*!< Log sequence number of
145 					the oldest modification */
146 	index_id_t	index_id;	/*!< Index ID if a index page */
147 };
148 
149 /** maximum number of buffer page info we would cache. */
150 #define MAX_BUF_INFO_CACHED		10000
151 
152 #define OK(expr)		\
153 	if ((expr) != 0) {	\
154 		DBUG_RETURN(1);	\
155 	}
156 
157 #define RETURN_IF_INNODB_NOT_STARTED(plugin_name)			\
158 do {									\
159 	if (!srv_was_started) {						\
160 		push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,	\
161 				    ER_CANT_FIND_SYSTEM_REC,		\
162 				    "InnoDB: SELECTing from "		\
163 				    "INFORMATION_SCHEMA.%s but "	\
164 				    "the InnoDB storage engine "	\
165 				    "is not installed", plugin_name);	\
166 		DBUG_RETURN(0);						\
167 	}								\
168 } while (0)
169 
170 #if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 &&	\
171 	!defined __INTEL_COMPILER && !defined __clang__
172 #define STRUCT_FLD(name, value)	name: value
173 #else
174 #define STRUCT_FLD(name, value)	value
175 #endif
176 
177 /* Don't use a static const variable here, as some C++ compilers (notably
178 HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
179 #define END_OF_ST_FIELD_INFO \
180 	{STRUCT_FLD(field_name,		NULL), \
181 	 STRUCT_FLD(field_length,	0), \
182 	 STRUCT_FLD(field_type,		MYSQL_TYPE_NULL), \
183 	 STRUCT_FLD(value,		0), \
184 	 STRUCT_FLD(field_flags,	0), \
185 	 STRUCT_FLD(old_name,		""), \
186 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)}
187 
188 /*
189 Use the following types mapping:
190 
191 C type	ST_FIELD_INFO::field_type
192 ---------------------------------
193 long			MYSQL_TYPE_LONGLONG
194 (field_length=MY_INT64_NUM_DECIMAL_DIGITS)
195 
196 long unsigned		MYSQL_TYPE_LONGLONG
197 (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
198 
199 char*			MYSQL_TYPE_STRING
200 (field_length=n)
201 
202 float			MYSQL_TYPE_FLOAT
203 (field_length=0 is ignored)
204 
205 void*			MYSQL_TYPE_LONGLONG
206 (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
207 
208 boolean (if else)	MYSQL_TYPE_LONG
209 (field_length=1)
210 
211 time_t			MYSQL_TYPE_DATETIME
212 (field_length=0 ignored)
213 ---------------------------------
214 */
215 
216 /*******************************************************************//**
217 Common function to fill any of the dynamic tables:
218 INFORMATION_SCHEMA.innodb_trx
219 INFORMATION_SCHEMA.innodb_locks
220 INFORMATION_SCHEMA.innodb_lock_waits
221 @return	0 on success */
222 static
223 int
224 trx_i_s_common_fill_table(
225 /*======================*/
226 	THD*		thd,	/*!< in: thread */
227 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
228 	Item*		);	/*!< in: condition (not used) */
229 
230 /*******************************************************************//**
231 Unbind a dynamic INFORMATION_SCHEMA table.
232 @return	0 on success */
233 static
234 int
235 i_s_common_deinit(
236 /*==============*/
237 	void*	p);	/*!< in/out: table schema object */
238 /*******************************************************************//**
239 Auxiliary function to store time_t value in MYSQL_TYPE_DATETIME
240 field.
241 @return	0 on success */
242 static
243 int
field_store_time_t(Field * field,time_t time)244 field_store_time_t(
245 /*===============*/
246 	Field*	field,	/*!< in/out: target field for storage */
247 	time_t	time)	/*!< in: value to store */
248 {
249 	MYSQL_TIME	my_time;
250 	struct tm	tm_time;
251 
252 	if (time) {
253 #if 0
254 		/* use this if you are sure that `variables' and `time_zone'
255 		are always initialized */
256 		thd->variables.time_zone->gmt_sec_to_TIME(
257 			&my_time, (my_time_t) time);
258 #else
259 		localtime_r(&time, &tm_time);
260 		localtime_to_TIME(&my_time, &tm_time);
261 		my_time.time_type = MYSQL_TIMESTAMP_DATETIME;
262 #endif
263 	} else {
264 		memset(&my_time, 0, sizeof(my_time));
265 	}
266 
267 	return(field->store_time(&my_time, MYSQL_TIMESTAMP_DATETIME));
268 }
269 
270 /*******************************************************************//**
271 Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
272 @return	0 on success */
273 static
274 int
field_store_string(Field * field,const char * str)275 field_store_string(
276 /*===============*/
277 	Field*		field,	/*!< in/out: target field for storage */
278 	const char*	str)	/*!< in: NUL-terminated utf-8 string,
279 				or NULL */
280 {
281 	int	ret;
282 
283 	if (str != NULL) {
284 
285 		ret = field->store(str, static_cast<uint>(strlen(str)),
286 				   system_charset_info);
287 		field->set_notnull();
288 	} else {
289 
290 		ret = 0; /* success */
291 		field->set_null();
292 	}
293 
294 	return(ret);
295 }
296 
297 /*******************************************************************//**
298 Store the name of an index in a MYSQL_TYPE_VARCHAR field.
299 Handles the names of incomplete secondary indexes.
300 @return	0 on success */
301 static
302 int
field_store_index_name(Field * field,const char * index_name)303 field_store_index_name(
304 /*===================*/
305 	Field*		field,		/*!< in/out: target field for
306 					storage */
307 	const char*	index_name)	/*!< in: NUL-terminated utf-8
308 					index name, possibly starting with
309 					TEMP_INDEX_PREFIX */
310 {
311 	int	ret;
312 
313 	ut_ad(index_name != NULL);
314 	ut_ad(field->real_type() == MYSQL_TYPE_VARCHAR);
315 
316 	/* Since TEMP_INDEX_PREFIX is not a valid UTF8, we need to convert
317 	it to something else. */
318 	if (index_name[0] == TEMP_INDEX_PREFIX) {
319 		char	buf[NAME_LEN + 1];
320 		buf[0] = '?';
321 		memcpy(buf + 1, index_name + 1, strlen(index_name));
322 		ret = field->store(
323 			buf, static_cast<uint>(strlen(buf)),
324 			system_charset_info);
325 	} else {
326 		ret = field->store(
327 			index_name, static_cast<uint>(strlen(index_name)),
328 			system_charset_info);
329 	}
330 
331 	field->set_notnull();
332 
333 	return(ret);
334 }
335 
336 /*******************************************************************//**
337 Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
338 If the value is ULINT_UNDEFINED then the field it set to NULL.
339 @return	0 on success */
340 static
341 int
field_store_ulint(Field * field,ulint n)342 field_store_ulint(
343 /*==============*/
344 	Field*	field,	/*!< in/out: target field for storage */
345 	ulint	n)	/*!< in: value to store */
346 {
347 	int	ret;
348 
349 	if (n != ULINT_UNDEFINED) {
350 
351 		ret = field->store(static_cast<double>(n));
352 		field->set_notnull();
353 	} else {
354 
355 		ret = 0; /* success */
356 		field->set_null();
357 	}
358 
359 	return(ret);
360 }
361 
362 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
363 static ST_FIELD_INFO	innodb_trx_fields_info[] =
364 {
365 #define IDX_TRX_ID		0
366 	{STRUCT_FLD(field_name,		"trx_id"),
367 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
368 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
369 	 STRUCT_FLD(value,		0),
370 	 STRUCT_FLD(field_flags,	0),
371 	 STRUCT_FLD(old_name,		""),
372 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
373 
374 #define IDX_TRX_STATE		1
375 	{STRUCT_FLD(field_name,		"trx_state"),
376 	 STRUCT_FLD(field_length,	TRX_QUE_STATE_STR_MAX_LEN + 1),
377 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
378 	 STRUCT_FLD(value,		0),
379 	 STRUCT_FLD(field_flags,	0),
380 	 STRUCT_FLD(old_name,		""),
381 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
382 
383 #define IDX_TRX_STARTED		2
384 	{STRUCT_FLD(field_name,		"trx_started"),
385 	 STRUCT_FLD(field_length,	0),
386 	 STRUCT_FLD(field_type,		MYSQL_TYPE_DATETIME),
387 	 STRUCT_FLD(value,		0),
388 	 STRUCT_FLD(field_flags,	0),
389 	 STRUCT_FLD(old_name,		""),
390 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
391 
392 #define IDX_TRX_REQUESTED_LOCK_ID	3
393 	{STRUCT_FLD(field_name,		"trx_requested_lock_id"),
394 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
395 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
396 	 STRUCT_FLD(value,		0),
397 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
398 	 STRUCT_FLD(old_name,		""),
399 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
400 
401 #define IDX_TRX_WAIT_STARTED	4
402 	{STRUCT_FLD(field_name,		"trx_wait_started"),
403 	 STRUCT_FLD(field_length,	0),
404 	 STRUCT_FLD(field_type,		MYSQL_TYPE_DATETIME),
405 	 STRUCT_FLD(value,		0),
406 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
407 	 STRUCT_FLD(old_name,		""),
408 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
409 
410 #define IDX_TRX_WEIGHT		5
411 	{STRUCT_FLD(field_name,		"trx_weight"),
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_MYSQL_THREAD_ID	6
420 	{STRUCT_FLD(field_name,		"trx_mysql_thread_id"),
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_QUERY		7
429 	{STRUCT_FLD(field_name,		"trx_query"),
430 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_QUERY_MAX_LEN),
431 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
432 	 STRUCT_FLD(value,		0),
433 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
434 	 STRUCT_FLD(old_name,		""),
435 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
436 
437 #define IDX_TRX_OPERATION_STATE	8
438 	{STRUCT_FLD(field_name,		"trx_operation_state"),
439 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_OP_STATE_MAX_LEN),
440 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
441 	 STRUCT_FLD(value,		0),
442 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
443 	 STRUCT_FLD(old_name,		""),
444 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
445 
446 #define IDX_TRX_TABLES_IN_USE	9
447 	{STRUCT_FLD(field_name,		"trx_tables_in_use"),
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_TABLES_LOCKED	10
456 	{STRUCT_FLD(field_name,		"trx_tables_locked"),
457 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
458 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
459 	 STRUCT_FLD(value,		0),
460 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
461 	 STRUCT_FLD(old_name,		""),
462 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
463 
464 #define IDX_TRX_LOCK_STRUCTS	11
465 	{STRUCT_FLD(field_name,		"trx_lock_structs"),
466 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
467 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
468 	 STRUCT_FLD(value,		0),
469 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
470 	 STRUCT_FLD(old_name,		""),
471 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
472 
473 #define IDX_TRX_LOCK_MEMORY_BYTES	12
474 	{STRUCT_FLD(field_name,		"trx_lock_memory_bytes"),
475 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
476 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
477 	 STRUCT_FLD(value,		0),
478 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
479 	 STRUCT_FLD(old_name,		""),
480 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
481 
482 #define IDX_TRX_ROWS_LOCKED	13
483 	{STRUCT_FLD(field_name,		"trx_rows_locked"),
484 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
485 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
486 	 STRUCT_FLD(value,		0),
487 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
488 	 STRUCT_FLD(old_name,		""),
489 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
490 
491 #define IDX_TRX_ROWS_MODIFIED		14
492 	{STRUCT_FLD(field_name,		"trx_rows_modified"),
493 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
494 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
495 	 STRUCT_FLD(value,		0),
496 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
497 	 STRUCT_FLD(old_name,		""),
498 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
499 
500 #define IDX_TRX_CONNCURRENCY_TICKETS	15
501 	{STRUCT_FLD(field_name,		"trx_concurrency_tickets"),
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 #define IDX_TRX_ISOLATION_LEVEL	16
510 	{STRUCT_FLD(field_name,		"trx_isolation_level"),
511 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_ISOLATION_LEVEL_MAX_LEN),
512 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
513 	 STRUCT_FLD(value,		0),
514 	 STRUCT_FLD(field_flags,	0),
515 	 STRUCT_FLD(old_name,		""),
516 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
517 
518 #define IDX_TRX_UNIQUE_CHECKS	17
519 	{STRUCT_FLD(field_name,		"trx_unique_checks"),
520 	 STRUCT_FLD(field_length,	1),
521 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
522 	 STRUCT_FLD(value,		1),
523 	 STRUCT_FLD(field_flags,	0),
524 	 STRUCT_FLD(old_name,		""),
525 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
526 
527 #define IDX_TRX_FOREIGN_KEY_CHECKS	18
528 	{STRUCT_FLD(field_name,		"trx_foreign_key_checks"),
529 	 STRUCT_FLD(field_length,	1),
530 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
531 	 STRUCT_FLD(value,		1),
532 	 STRUCT_FLD(field_flags,	0),
533 	 STRUCT_FLD(old_name,		""),
534 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
535 
536 #define IDX_TRX_LAST_FOREIGN_KEY_ERROR	19
537 	{STRUCT_FLD(field_name,		"trx_last_foreign_key_error"),
538 	 STRUCT_FLD(field_length,	TRX_I_S_TRX_FK_ERROR_MAX_LEN),
539 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
540 	 STRUCT_FLD(value,		0),
541 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
542 	 STRUCT_FLD(old_name,		""),
543 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
544 
545 #define IDX_TRX_ADAPTIVE_HASH_LATCHED	20
546 	{STRUCT_FLD(field_name,		"trx_adaptive_hash_latched"),
547 	 STRUCT_FLD(field_length,	1),
548 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
549 	 STRUCT_FLD(value,		0),
550 	 STRUCT_FLD(field_flags,	0),
551 	 STRUCT_FLD(old_name,		""),
552 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
553 
554 #define IDX_TRX_ADAPTIVE_HASH_TIMEOUT	21
555 	{STRUCT_FLD(field_name,		"trx_adaptive_hash_timeout"),
556 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
557 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
558 	 STRUCT_FLD(value,		0),
559 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
560 	 STRUCT_FLD(old_name,		""),
561 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
562 
563 #define IDX_TRX_READ_ONLY		22
564 	{STRUCT_FLD(field_name,		"trx_is_read_only"),
565 	 STRUCT_FLD(field_length,	1),
566 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
567 	 STRUCT_FLD(value,		0),
568 	 STRUCT_FLD(field_flags,	0),
569 	 STRUCT_FLD(old_name,		""),
570 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
571 
572 #define IDX_TRX_AUTOCOMMIT_NON_LOCKING	23
573 	{STRUCT_FLD(field_name,		"trx_autocommit_non_locking"),
574 	 STRUCT_FLD(field_length,	1),
575 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
576 	 STRUCT_FLD(value,		0),
577 	 STRUCT_FLD(field_flags,	0),
578 	 STRUCT_FLD(old_name,		""),
579 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
580 
581 	END_OF_ST_FIELD_INFO
582 };
583 
584 /*******************************************************************//**
585 Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_trx
586 table with it.
587 @return	0 on success */
588 static
589 int
fill_innodb_trx_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)590 fill_innodb_trx_from_cache(
591 /*=======================*/
592 	trx_i_s_cache_t*	cache,	/*!< in: cache to read from */
593 	THD*			thd,	/*!< in: used to call
594 					schema_table_store_record() */
595 	TABLE*			table)	/*!< in/out: fill this table */
596 {
597 	Field**	fields;
598 	ulint	rows_num;
599 	char	lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
600 	ulint	i;
601 
602 	DBUG_ENTER("fill_innodb_trx_from_cache");
603 
604 	fields = table->field;
605 
606 	rows_num = trx_i_s_cache_get_rows_used(cache,
607 					       I_S_INNODB_TRX);
608 
609 	for (i = 0; i < rows_num; i++) {
610 
611 		i_s_trx_row_t*	row;
612 		char		trx_id[TRX_ID_MAX_LEN + 1];
613 
614 		row = (i_s_trx_row_t*)
615 			trx_i_s_cache_get_nth_row(
616 				cache, I_S_INNODB_TRX, i);
617 
618 		/* trx_id */
619 		ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
620 		OK(field_store_string(fields[IDX_TRX_ID], trx_id));
621 
622 		/* trx_state */
623 		OK(field_store_string(fields[IDX_TRX_STATE],
624 				      row->trx_state));
625 
626 		/* trx_started */
627 		OK(field_store_time_t(fields[IDX_TRX_STARTED],
628 				      (time_t) row->trx_started));
629 
630 		/* trx_requested_lock_id */
631 		/* trx_wait_started */
632 		if (row->trx_wait_started != 0) {
633 
634 			OK(field_store_string(
635 				   fields[IDX_TRX_REQUESTED_LOCK_ID],
636 				   trx_i_s_create_lock_id(
637 					   row->requested_lock_row,
638 					   lock_id, sizeof(lock_id))));
639 			/* field_store_string() sets it no notnull */
640 
641 			OK(field_store_time_t(
642 				   fields[IDX_TRX_WAIT_STARTED],
643 				   (time_t) row->trx_wait_started));
644 			fields[IDX_TRX_WAIT_STARTED]->set_notnull();
645 		} else {
646 
647 			fields[IDX_TRX_REQUESTED_LOCK_ID]->set_null();
648 			fields[IDX_TRX_WAIT_STARTED]->set_null();
649 		}
650 
651 		/* trx_weight */
652 		OK(fields[IDX_TRX_WEIGHT]->store((longlong) row->trx_weight,
653 						 true));
654 
655 		/* trx_mysql_thread_id */
656 		OK(fields[IDX_TRX_MYSQL_THREAD_ID]->store(
657 			   static_cast<double>(row->trx_mysql_thread_id)));
658 
659 		/* trx_query */
660 		if (row->trx_query) {
661 			/* store will do appropriate character set
662 			conversion check */
663 			fields[IDX_TRX_QUERY]->store(
664 				row->trx_query,
665 				static_cast<uint>(strlen(row->trx_query)),
666 				row->trx_query_cs);
667 			fields[IDX_TRX_QUERY]->set_notnull();
668 		} else {
669 			fields[IDX_TRX_QUERY]->set_null();
670 		}
671 
672 		/* trx_operation_state */
673 		OK(field_store_string(fields[IDX_TRX_OPERATION_STATE],
674 				      row->trx_operation_state));
675 
676 		/* trx_tables_in_use */
677 		OK(fields[IDX_TRX_TABLES_IN_USE]->store(
678 			   (longlong) row->trx_tables_in_use, true));
679 
680 		/* trx_tables_locked */
681 		OK(fields[IDX_TRX_TABLES_LOCKED]->store(
682 			   (longlong) row->trx_tables_locked, true));
683 
684 		/* trx_lock_structs */
685 		OK(fields[IDX_TRX_LOCK_STRUCTS]->store(
686 			   (longlong) row->trx_lock_structs, true));
687 
688 		/* trx_lock_memory_bytes */
689 		OK(fields[IDX_TRX_LOCK_MEMORY_BYTES]->store(
690 			   (longlong) row->trx_lock_memory_bytes, true));
691 
692 		/* trx_rows_locked */
693 		OK(fields[IDX_TRX_ROWS_LOCKED]->store(
694 			   (longlong) row->trx_rows_locked, true));
695 
696 		/* trx_rows_modified */
697 		OK(fields[IDX_TRX_ROWS_MODIFIED]->store(
698 			   (longlong) row->trx_rows_modified, true));
699 
700 		/* trx_concurrency_tickets */
701 		OK(fields[IDX_TRX_CONNCURRENCY_TICKETS]->store(
702 			   (longlong) row->trx_concurrency_tickets, true));
703 
704 		/* trx_isolation_level */
705 		OK(field_store_string(fields[IDX_TRX_ISOLATION_LEVEL],
706 				      row->trx_isolation_level));
707 
708 		/* trx_unique_checks */
709 		OK(fields[IDX_TRX_UNIQUE_CHECKS]->store(
710 			   static_cast<double>(row->trx_unique_checks)));
711 
712 		/* trx_foreign_key_checks */
713 		OK(fields[IDX_TRX_FOREIGN_KEY_CHECKS]->store(
714 			   static_cast<double>(row->trx_foreign_key_checks)));
715 
716 		/* trx_last_foreign_key_error */
717 		OK(field_store_string(fields[IDX_TRX_LAST_FOREIGN_KEY_ERROR],
718 				      row->trx_foreign_key_error));
719 
720 		/* trx_adaptive_hash_latched */
721 		OK(fields[IDX_TRX_ADAPTIVE_HASH_LATCHED]->store(
722 			   static_cast<double>(row->trx_has_search_latch)));
723 
724 		/* trx_adaptive_hash_timeout */
725 		OK(fields[IDX_TRX_ADAPTIVE_HASH_TIMEOUT]->store(
726 			   (longlong) row->trx_search_latch_timeout, true));
727 
728 		/* trx_is_read_only*/
729 		OK(fields[IDX_TRX_READ_ONLY]->store(
730 				(longlong) row->trx_is_read_only, true));
731 
732 		/* trx_is_autocommit_non_locking */
733 		OK(fields[IDX_TRX_AUTOCOMMIT_NON_LOCKING]->store(
734 				(longlong) row->trx_is_autocommit_non_locking,
735 				true));
736 
737 		OK(schema_table_store_record(thd, table));
738 	}
739 
740 	DBUG_RETURN(0);
741 }
742 
743 /*******************************************************************//**
744 Bind the dynamic table INFORMATION_SCHEMA.innodb_trx
745 @return	0 on success */
746 static
747 int
innodb_trx_init(void * p)748 innodb_trx_init(
749 /*============*/
750 	void*	p)	/*!< in/out: table schema object */
751 {
752 	ST_SCHEMA_TABLE*	schema;
753 
754 	DBUG_ENTER("innodb_trx_init");
755 
756 	schema = (ST_SCHEMA_TABLE*) p;
757 
758 	schema->fields_info = innodb_trx_fields_info;
759 	schema->fill_table = trx_i_s_common_fill_table;
760 
761 	DBUG_RETURN(0);
762 }
763 
764 static struct st_mysql_information_schema	i_s_info =
765 {
766 	MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
767 };
768 
769 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_trx =
770 {
771 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
772 	/* int */
773 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
774 
775 	/* pointer to type-specific plugin descriptor */
776 	/* void* */
777 	STRUCT_FLD(info, &i_s_info),
778 
779 	/* plugin name */
780 	/* const char* */
781 	STRUCT_FLD(name, "INNODB_TRX"),
782 
783 	/* plugin author (for SHOW PLUGINS) */
784 	/* const char* */
785 	STRUCT_FLD(author, plugin_author),
786 
787 	/* general descriptive text (for SHOW PLUGINS) */
788 	/* const char* */
789 	STRUCT_FLD(descr, "InnoDB transactions"),
790 
791 	/* the plugin license (PLUGIN_LICENSE_XXX) */
792 	/* int */
793 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
794 
795 	/* the function to invoke when plugin is loaded */
796 	/* int (*)(void*); */
797 	STRUCT_FLD(init, innodb_trx_init),
798 
799 	/* the function to invoke when plugin is unloaded */
800 	/* int (*)(void*); */
801 	STRUCT_FLD(deinit, i_s_common_deinit),
802 
803 	/* plugin version (for SHOW PLUGINS) */
804 	/* unsigned int */
805 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
806 
807 	/* struct st_mysql_show_var* */
808 	STRUCT_FLD(status_vars, NULL),
809 
810 	/* struct st_mysql_sys_var** */
811 	STRUCT_FLD(system_vars, NULL),
812 
813 	/* reserved for dependency checking */
814 	/* void* */
815 	STRUCT_FLD(__reserved1, NULL),
816 
817 	/* Plugin flags */
818 	/* unsigned long */
819 	STRUCT_FLD(flags, 0UL),
820 };
821 
822 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
823 static ST_FIELD_INFO	innodb_locks_fields_info[] =
824 {
825 #define IDX_LOCK_ID		0
826 	{STRUCT_FLD(field_name,		"lock_id"),
827 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
828 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
829 	 STRUCT_FLD(value,		0),
830 	 STRUCT_FLD(field_flags,	0),
831 	 STRUCT_FLD(old_name,		""),
832 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
833 
834 #define IDX_LOCK_TRX_ID		1
835 	{STRUCT_FLD(field_name,		"lock_trx_id"),
836 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
837 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
838 	 STRUCT_FLD(value,		0),
839 	 STRUCT_FLD(field_flags,	0),
840 	 STRUCT_FLD(old_name,		""),
841 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
842 
843 #define IDX_LOCK_MODE		2
844 	{STRUCT_FLD(field_name,		"lock_mode"),
845 	 /* S[,GAP] X[,GAP] IS[,GAP] IX[,GAP] AUTO_INC UNKNOWN */
846 	 STRUCT_FLD(field_length,	32),
847 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
848 	 STRUCT_FLD(value,		0),
849 	 STRUCT_FLD(field_flags,	0),
850 	 STRUCT_FLD(old_name,		""),
851 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
852 
853 #define IDX_LOCK_TYPE		3
854 	{STRUCT_FLD(field_name,		"lock_type"),
855 	 STRUCT_FLD(field_length,	32 /* RECORD|TABLE|UNKNOWN */),
856 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
857 	 STRUCT_FLD(value,		0),
858 	 STRUCT_FLD(field_flags,	0),
859 	 STRUCT_FLD(old_name,		""),
860 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
861 
862 #define IDX_LOCK_TABLE		4
863 	{STRUCT_FLD(field_name,		"lock_table"),
864 	 STRUCT_FLD(field_length,	1024),
865 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
866 	 STRUCT_FLD(value,		0),
867 	 STRUCT_FLD(field_flags,	0),
868 	 STRUCT_FLD(old_name,		""),
869 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
870 
871 #define IDX_LOCK_INDEX		5
872 	{STRUCT_FLD(field_name,		"lock_index"),
873 	 STRUCT_FLD(field_length,	1024),
874 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
875 	 STRUCT_FLD(value,		0),
876 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
877 	 STRUCT_FLD(old_name,		""),
878 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
879 
880 #define IDX_LOCK_SPACE		6
881 	{STRUCT_FLD(field_name,		"lock_space"),
882 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
883 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
884 	 STRUCT_FLD(value,		0),
885 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
886 	 STRUCT_FLD(old_name,		""),
887 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
888 
889 #define IDX_LOCK_PAGE		7
890 	{STRUCT_FLD(field_name,		"lock_page"),
891 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
892 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
893 	 STRUCT_FLD(value,		0),
894 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
895 	 STRUCT_FLD(old_name,		""),
896 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
897 
898 #define IDX_LOCK_REC		8
899 	{STRUCT_FLD(field_name,		"lock_rec"),
900 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
901 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
902 	 STRUCT_FLD(value,		0),
903 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
904 	 STRUCT_FLD(old_name,		""),
905 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
906 
907 #define IDX_LOCK_DATA		9
908 	{STRUCT_FLD(field_name,		"lock_data"),
909 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_DATA_MAX_LEN),
910 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
911 	 STRUCT_FLD(value,		0),
912 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
913 	 STRUCT_FLD(old_name,		""),
914 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
915 
916 	END_OF_ST_FIELD_INFO
917 };
918 
919 /*******************************************************************//**
920 Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_locks
921 table with it.
922 @return	0 on success */
923 static
924 int
fill_innodb_locks_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)925 fill_innodb_locks_from_cache(
926 /*=========================*/
927 	trx_i_s_cache_t*	cache,	/*!< in: cache to read from */
928 	THD*			thd,	/*!< in: MySQL client connection */
929 	TABLE*			table)	/*!< in/out: fill this table */
930 {
931 	Field**	fields;
932 	ulint	rows_num;
933 	char	lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
934 	ulint	i;
935 
936 	DBUG_ENTER("fill_innodb_locks_from_cache");
937 
938 	fields = table->field;
939 
940 	rows_num = trx_i_s_cache_get_rows_used(cache,
941 					       I_S_INNODB_LOCKS);
942 
943 	for (i = 0; i < rows_num; i++) {
944 
945 		i_s_locks_row_t*	row;
946 		char			buf[MAX_FULL_NAME_LEN + 1];
947 		const char*		bufend;
948 
949 		char			lock_trx_id[TRX_ID_MAX_LEN + 1];
950 
951 		row = (i_s_locks_row_t*)
952 			trx_i_s_cache_get_nth_row(
953 				cache, I_S_INNODB_LOCKS, i);
954 
955 		/* lock_id */
956 		trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
957 		OK(field_store_string(fields[IDX_LOCK_ID],
958 				      lock_id));
959 
960 		/* lock_trx_id */
961 		ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
962 			    TRX_ID_FMT, row->lock_trx_id);
963 		OK(field_store_string(fields[IDX_LOCK_TRX_ID], lock_trx_id));
964 
965 		/* lock_mode */
966 		OK(field_store_string(fields[IDX_LOCK_MODE],
967 				      row->lock_mode));
968 
969 		/* lock_type */
970 		OK(field_store_string(fields[IDX_LOCK_TYPE],
971 				      row->lock_type));
972 
973 		/* lock_table */
974 		bufend = innobase_convert_name(buf, sizeof(buf),
975 					       row->lock_table,
976 					       strlen(row->lock_table),
977 					       thd, TRUE);
978 		OK(fields[IDX_LOCK_TABLE]->store(
979 			buf, static_cast<uint>(bufend - buf),
980 			system_charset_info));
981 
982 		/* lock_index */
983 		if (row->lock_index != NULL) {
984 			OK(field_store_index_name(fields[IDX_LOCK_INDEX],
985 						  row->lock_index));
986 		} else {
987 			fields[IDX_LOCK_INDEX]->set_null();
988 		}
989 
990 		/* lock_space */
991 		OK(field_store_ulint(fields[IDX_LOCK_SPACE],
992 				     row->lock_space));
993 
994 		/* lock_page */
995 		OK(field_store_ulint(fields[IDX_LOCK_PAGE],
996 				     row->lock_page));
997 
998 		/* lock_rec */
999 		OK(field_store_ulint(fields[IDX_LOCK_REC],
1000 				     row->lock_rec));
1001 
1002 		/* lock_data */
1003 		OK(field_store_string(fields[IDX_LOCK_DATA],
1004 				      row->lock_data));
1005 
1006 		OK(schema_table_store_record(thd, table));
1007 	}
1008 
1009 	DBUG_RETURN(0);
1010 }
1011 
1012 /*******************************************************************//**
1013 Bind the dynamic table INFORMATION_SCHEMA.innodb_locks
1014 @return	0 on success */
1015 static
1016 int
innodb_locks_init(void * p)1017 innodb_locks_init(
1018 /*==============*/
1019 	void*	p)	/*!< in/out: table schema object */
1020 {
1021 	ST_SCHEMA_TABLE*	schema;
1022 
1023 	DBUG_ENTER("innodb_locks_init");
1024 
1025 	schema = (ST_SCHEMA_TABLE*) p;
1026 
1027 	schema->fields_info = innodb_locks_fields_info;
1028 	schema->fill_table = trx_i_s_common_fill_table;
1029 
1030 	DBUG_RETURN(0);
1031 }
1032 
1033 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_locks =
1034 {
1035 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1036 	/* int */
1037 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1038 
1039 	/* pointer to type-specific plugin descriptor */
1040 	/* void* */
1041 	STRUCT_FLD(info, &i_s_info),
1042 
1043 	/* plugin name */
1044 	/* const char* */
1045 	STRUCT_FLD(name, "INNODB_LOCKS"),
1046 
1047 	/* plugin author (for SHOW PLUGINS) */
1048 	/* const char* */
1049 	STRUCT_FLD(author, plugin_author),
1050 
1051 	/* general descriptive text (for SHOW PLUGINS) */
1052 	/* const char* */
1053 	STRUCT_FLD(descr, "InnoDB conflicting locks"),
1054 
1055 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1056 	/* int */
1057 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1058 
1059 	/* the function to invoke when plugin is loaded */
1060 	/* int (*)(void*); */
1061 	STRUCT_FLD(init, innodb_locks_init),
1062 
1063 	/* the function to invoke when plugin is unloaded */
1064 	/* int (*)(void*); */
1065 	STRUCT_FLD(deinit, i_s_common_deinit),
1066 
1067 	/* plugin version (for SHOW PLUGINS) */
1068 	/* unsigned int */
1069 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1070 
1071 	/* struct st_mysql_show_var* */
1072 	STRUCT_FLD(status_vars, NULL),
1073 
1074 	/* struct st_mysql_sys_var** */
1075 	STRUCT_FLD(system_vars, NULL),
1076 
1077 	/* reserved for dependency checking */
1078 	/* void* */
1079 	STRUCT_FLD(__reserved1, NULL),
1080 
1081 	/* Plugin flags */
1082 	/* unsigned long */
1083 	STRUCT_FLD(flags, 0UL),
1084 };
1085 
1086 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
1087 static ST_FIELD_INFO	innodb_lock_waits_fields_info[] =
1088 {
1089 #define IDX_REQUESTING_TRX_ID	0
1090 	{STRUCT_FLD(field_name,		"requesting_trx_id"),
1091 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
1092 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1093 	 STRUCT_FLD(value,		0),
1094 	 STRUCT_FLD(field_flags,	0),
1095 	 STRUCT_FLD(old_name,		""),
1096 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1097 
1098 #define IDX_REQUESTED_LOCK_ID	1
1099 	{STRUCT_FLD(field_name,		"requested_lock_id"),
1100 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
1101 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1102 	 STRUCT_FLD(value,		0),
1103 	 STRUCT_FLD(field_flags,	0),
1104 	 STRUCT_FLD(old_name,		""),
1105 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1106 
1107 #define IDX_BLOCKING_TRX_ID	2
1108 	{STRUCT_FLD(field_name,		"blocking_trx_id"),
1109 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
1110 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1111 	 STRUCT_FLD(value,		0),
1112 	 STRUCT_FLD(field_flags,	0),
1113 	 STRUCT_FLD(old_name,		""),
1114 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1115 
1116 #define IDX_BLOCKING_LOCK_ID	3
1117 	{STRUCT_FLD(field_name,		"blocking_lock_id"),
1118 	 STRUCT_FLD(field_length,	TRX_I_S_LOCK_ID_MAX_LEN + 1),
1119 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1120 	 STRUCT_FLD(value,		0),
1121 	 STRUCT_FLD(field_flags,	0),
1122 	 STRUCT_FLD(old_name,		""),
1123 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1124 
1125 	END_OF_ST_FIELD_INFO
1126 };
1127 
1128 /*******************************************************************//**
1129 Read data from cache buffer and fill the
1130 INFORMATION_SCHEMA.innodb_lock_waits table with it.
1131 @return	0 on success */
1132 static
1133 int
fill_innodb_lock_waits_from_cache(trx_i_s_cache_t * cache,THD * thd,TABLE * table)1134 fill_innodb_lock_waits_from_cache(
1135 /*==============================*/
1136 	trx_i_s_cache_t*	cache,	/*!< in: cache to read from */
1137 	THD*			thd,	/*!< in: used to call
1138 					schema_table_store_record() */
1139 	TABLE*			table)	/*!< in/out: fill this table */
1140 {
1141 	Field**	fields;
1142 	ulint	rows_num;
1143 	char	requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
1144 	char	blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
1145 	ulint	i;
1146 
1147 	DBUG_ENTER("fill_innodb_lock_waits_from_cache");
1148 
1149 	fields = table->field;
1150 
1151 	rows_num = trx_i_s_cache_get_rows_used(cache,
1152 					       I_S_INNODB_LOCK_WAITS);
1153 
1154 	for (i = 0; i < rows_num; i++) {
1155 
1156 		i_s_lock_waits_row_t*	row;
1157 
1158 		char	requesting_trx_id[TRX_ID_MAX_LEN + 1];
1159 		char	blocking_trx_id[TRX_ID_MAX_LEN + 1];
1160 
1161 		row = (i_s_lock_waits_row_t*)
1162 			trx_i_s_cache_get_nth_row(
1163 				cache, I_S_INNODB_LOCK_WAITS, i);
1164 
1165 		/* requesting_trx_id */
1166 		ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
1167 			    TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
1168 		OK(field_store_string(fields[IDX_REQUESTING_TRX_ID],
1169 				      requesting_trx_id));
1170 
1171 		/* requested_lock_id */
1172 		OK(field_store_string(
1173 			   fields[IDX_REQUESTED_LOCK_ID],
1174 			   trx_i_s_create_lock_id(
1175 				   row->requested_lock_row,
1176 				   requested_lock_id,
1177 				   sizeof(requested_lock_id))));
1178 
1179 		/* blocking_trx_id */
1180 		ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
1181 			    TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
1182 		OK(field_store_string(fields[IDX_BLOCKING_TRX_ID],
1183 				      blocking_trx_id));
1184 
1185 		/* blocking_lock_id */
1186 		OK(field_store_string(
1187 			   fields[IDX_BLOCKING_LOCK_ID],
1188 			   trx_i_s_create_lock_id(
1189 				   row->blocking_lock_row,
1190 				   blocking_lock_id,
1191 				   sizeof(blocking_lock_id))));
1192 
1193 		OK(schema_table_store_record(thd, table));
1194 	}
1195 
1196 	DBUG_RETURN(0);
1197 }
1198 
1199 /*******************************************************************//**
1200 Bind the dynamic table INFORMATION_SCHEMA.innodb_lock_waits
1201 @return	0 on success */
1202 static
1203 int
innodb_lock_waits_init(void * p)1204 innodb_lock_waits_init(
1205 /*===================*/
1206 	void*	p)	/*!< in/out: table schema object */
1207 {
1208 	ST_SCHEMA_TABLE*	schema;
1209 
1210 	DBUG_ENTER("innodb_lock_waits_init");
1211 
1212 	schema = (ST_SCHEMA_TABLE*) p;
1213 
1214 	schema->fields_info = innodb_lock_waits_fields_info;
1215 	schema->fill_table = trx_i_s_common_fill_table;
1216 
1217 	DBUG_RETURN(0);
1218 }
1219 
1220 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_lock_waits =
1221 {
1222 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1223 	/* int */
1224 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1225 
1226 	/* pointer to type-specific plugin descriptor */
1227 	/* void* */
1228 	STRUCT_FLD(info, &i_s_info),
1229 
1230 	/* plugin name */
1231 	/* const char* */
1232 	STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
1233 
1234 	/* plugin author (for SHOW PLUGINS) */
1235 	/* const char* */
1236 	STRUCT_FLD(author, plugin_author),
1237 
1238 	/* general descriptive text (for SHOW PLUGINS) */
1239 	/* const char* */
1240 	STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
1241 
1242 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1243 	/* int */
1244 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1245 
1246 	/* the function to invoke when plugin is loaded */
1247 	/* int (*)(void*); */
1248 	STRUCT_FLD(init, innodb_lock_waits_init),
1249 
1250 	/* the function to invoke when plugin is unloaded */
1251 	/* int (*)(void*); */
1252 	STRUCT_FLD(deinit, i_s_common_deinit),
1253 
1254 	/* plugin version (for SHOW PLUGINS) */
1255 	/* unsigned int */
1256 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1257 
1258 	/* struct st_mysql_show_var* */
1259 	STRUCT_FLD(status_vars, NULL),
1260 
1261 	/* struct st_mysql_sys_var** */
1262 	STRUCT_FLD(system_vars, NULL),
1263 
1264 	/* reserved for dependency checking */
1265 	/* void* */
1266 	STRUCT_FLD(__reserved1, NULL),
1267 
1268 	/* Plugin flags */
1269 	/* unsigned long */
1270 	STRUCT_FLD(flags, 0UL),
1271 };
1272 
1273 /*******************************************************************//**
1274 Common function to fill any of the dynamic tables:
1275 INFORMATION_SCHEMA.innodb_trx
1276 INFORMATION_SCHEMA.innodb_locks
1277 INFORMATION_SCHEMA.innodb_lock_waits
1278 @return	0 on success */
1279 static
1280 int
trx_i_s_common_fill_table(THD * thd,TABLE_LIST * tables,Item *)1281 trx_i_s_common_fill_table(
1282 /*======================*/
1283 	THD*		thd,	/*!< in: thread */
1284 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1285 	Item*		)	/*!< in: condition (not used) */
1286 {
1287 	const char*		table_name;
1288 	int			ret;
1289 	trx_i_s_cache_t*	cache;
1290 
1291 	DBUG_ENTER("trx_i_s_common_fill_table");
1292 
1293 	/* deny access to non-superusers */
1294 	if (check_global_access(thd, PROCESS_ACL)) {
1295 
1296 		DBUG_RETURN(0);
1297 	}
1298 
1299 	/* minimize the number of places where global variables are
1300 	referenced */
1301 	cache = trx_i_s_cache;
1302 
1303 	/* which table we have to fill? */
1304 	table_name = tables->schema_table_name;
1305 	/* or table_name = tables->schema_table->table_name; */
1306 
1307 	RETURN_IF_INNODB_NOT_STARTED(table_name);
1308 
1309 	/* update the cache */
1310 	trx_i_s_cache_start_write(cache);
1311 	trx_i_s_possibly_fetch_data_into_cache(cache);
1312 	trx_i_s_cache_end_write(cache);
1313 
1314 	if (trx_i_s_cache_is_truncated(cache)) {
1315 
1316 		/* XXX show warning to user if possible */
1317 		fprintf(stderr, "Warning: data in %s truncated due to "
1318 			"memory limit of %d bytes\n", table_name,
1319 			TRX_I_S_MEM_LIMIT);
1320 	}
1321 
1322 	ret = 0;
1323 
1324 	trx_i_s_cache_start_read(cache);
1325 
1326 	if (innobase_strcasecmp(table_name, "innodb_trx") == 0) {
1327 
1328 		if (fill_innodb_trx_from_cache(
1329 			cache, thd, tables->table) != 0) {
1330 
1331 			ret = 1;
1332 		}
1333 
1334 	} else if (innobase_strcasecmp(table_name, "innodb_locks") == 0) {
1335 
1336 		if (fill_innodb_locks_from_cache(
1337 			cache, thd, tables->table) != 0) {
1338 
1339 			ret = 1;
1340 		}
1341 
1342 	} else if (innobase_strcasecmp(table_name, "innodb_lock_waits") == 0) {
1343 
1344 		if (fill_innodb_lock_waits_from_cache(
1345 			cache, thd, tables->table) != 0) {
1346 
1347 			ret = 1;
1348 		}
1349 
1350 	} else {
1351 
1352 		/* huh! what happened!? */
1353 		fprintf(stderr,
1354 			"InnoDB: trx_i_s_common_fill_table() was "
1355 			"called to fill unknown table: %s.\n"
1356 			"This function only knows how to fill "
1357 			"innodb_trx, innodb_locks and "
1358 			"innodb_lock_waits tables.\n", table_name);
1359 
1360 		ret = 1;
1361 	}
1362 
1363 	trx_i_s_cache_end_read(cache);
1364 
1365 #if 0
1366 	DBUG_RETURN(ret);
1367 #else
1368 	/* if this function returns something else than 0 then a
1369 	deadlock occurs between the mysqld server and mysql client,
1370 	see http://bugs.mysql.com/29900 ; when that bug is resolved
1371 	we can enable the DBUG_RETURN(ret) above */
1372 	ret++;  // silence a gcc46 warning
1373 	DBUG_RETURN(0);
1374 #endif
1375 }
1376 
1377 /* Fields of the dynamic table information_schema.innodb_cmp. */
1378 static ST_FIELD_INFO	i_s_cmp_fields_info[] =
1379 {
1380 	{STRUCT_FLD(field_name,		"page_size"),
1381 	 STRUCT_FLD(field_length,	5),
1382 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1383 	 STRUCT_FLD(value,		0),
1384 	 STRUCT_FLD(field_flags,	0),
1385 	 STRUCT_FLD(old_name,		"Compressed Page Size"),
1386 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1387 
1388 	{STRUCT_FLD(field_name,		"compress_ops"),
1389 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1390 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1391 	 STRUCT_FLD(value,		0),
1392 	 STRUCT_FLD(field_flags,	0),
1393 	 STRUCT_FLD(old_name,		"Total Number of Compressions"),
1394 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1395 
1396 	{STRUCT_FLD(field_name,		"compress_ops_ok"),
1397 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1398 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1399 	 STRUCT_FLD(value,		0),
1400 	 STRUCT_FLD(field_flags,	0),
1401 	 STRUCT_FLD(old_name,		"Total Number of"
1402 					" Successful Compressions"),
1403 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1404 
1405 	{STRUCT_FLD(field_name,		"compress_time"),
1406 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1407 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1408 	 STRUCT_FLD(value,		0),
1409 	 STRUCT_FLD(field_flags,	0),
1410 	 STRUCT_FLD(old_name,		"Total Duration of Compressions,"
1411 		    " in Seconds"),
1412 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1413 
1414 	{STRUCT_FLD(field_name,		"uncompress_ops"),
1415 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1416 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1417 	 STRUCT_FLD(value,		0),
1418 	 STRUCT_FLD(field_flags,	0),
1419 	 STRUCT_FLD(old_name,		"Total Number of Decompressions"),
1420 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1421 
1422 	{STRUCT_FLD(field_name,		"uncompress_time"),
1423 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1424 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1425 	 STRUCT_FLD(value,		0),
1426 	 STRUCT_FLD(field_flags,	0),
1427 	 STRUCT_FLD(old_name,		"Total Duration of Decompressions,"
1428 		    " in Seconds"),
1429 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1430 
1431 	END_OF_ST_FIELD_INFO
1432 };
1433 
1434 
1435 /*******************************************************************//**
1436 Fill the dynamic table information_schema.innodb_cmp or
1437 innodb_cmp_reset.
1438 @return	0 on success, 1 on failure */
1439 static
1440 int
i_s_cmp_fill_low(THD * thd,TABLE_LIST * tables,Item *,ibool reset)1441 i_s_cmp_fill_low(
1442 /*=============*/
1443 	THD*		thd,	/*!< in: thread */
1444 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1445 	Item*		,	/*!< in: condition (ignored) */
1446 	ibool		reset)	/*!< in: TRUE=reset cumulated counts */
1447 {
1448 	TABLE*	table	= (TABLE*) tables->table;
1449 	int	status	= 0;
1450 
1451 	DBUG_ENTER("i_s_cmp_fill_low");
1452 
1453 	/* deny access to non-superusers */
1454 	if (check_global_access(thd, PROCESS_ACL)) {
1455 
1456 		DBUG_RETURN(0);
1457 	}
1458 
1459 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
1460 
1461 	for (uint i = 0; i < PAGE_ZIP_SSIZE_MAX; i++) {
1462 		page_zip_stat_t*	zip_stat = &page_zip_stat[i];
1463 
1464 		table->field[0]->store(UNIV_ZIP_SIZE_MIN << i);
1465 
1466 		/* The cumulated counts are not protected by any
1467 		mutex.  Thus, some operation in page0zip.cc could
1468 		increment a counter between the time we read it and
1469 		clear it.  We could introduce mutex protection, but it
1470 		could cause a measureable performance hit in
1471 		page0zip.cc. */
1472 		table->field[1]->store(
1473 			static_cast<double>(zip_stat->compressed));
1474 		table->field[2]->store(
1475 			static_cast<double>(zip_stat->compressed_ok));
1476 		table->field[3]->store(
1477 			static_cast<double>(zip_stat->compressed_usec / 1000000));
1478 		table->field[4]->store(
1479 			static_cast<double>(zip_stat->decompressed));
1480 		table->field[5]->store(
1481 			static_cast<double>(zip_stat->decompressed_usec / 1000000));
1482 
1483 		if (reset) {
1484 			memset(zip_stat, 0, sizeof *zip_stat);
1485 		}
1486 
1487 		if (schema_table_store_record(thd, table)) {
1488 			status = 1;
1489 			break;
1490 		}
1491 	}
1492 
1493 	DBUG_RETURN(status);
1494 }
1495 
1496 /*******************************************************************//**
1497 Fill the dynamic table information_schema.innodb_cmp.
1498 @return	0 on success, 1 on failure */
1499 static
1500 int
i_s_cmp_fill(THD * thd,TABLE_LIST * tables,Item * cond)1501 i_s_cmp_fill(
1502 /*=========*/
1503 	THD*		thd,	/*!< in: thread */
1504 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1505 	Item*		cond)	/*!< in: condition (ignored) */
1506 {
1507 	return(i_s_cmp_fill_low(thd, tables, cond, FALSE));
1508 }
1509 
1510 /*******************************************************************//**
1511 Fill the dynamic table information_schema.innodb_cmp_reset.
1512 @return	0 on success, 1 on failure */
1513 static
1514 int
i_s_cmp_reset_fill(THD * thd,TABLE_LIST * tables,Item * cond)1515 i_s_cmp_reset_fill(
1516 /*===============*/
1517 	THD*		thd,	/*!< in: thread */
1518 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1519 	Item*		cond)	/*!< in: condition (ignored) */
1520 {
1521 	return(i_s_cmp_fill_low(thd, tables, cond, TRUE));
1522 }
1523 
1524 /*******************************************************************//**
1525 Bind the dynamic table information_schema.innodb_cmp.
1526 @return	0 on success */
1527 static
1528 int
i_s_cmp_init(void * p)1529 i_s_cmp_init(
1530 /*=========*/
1531 	void*	p)	/*!< in/out: table schema object */
1532 {
1533 	DBUG_ENTER("i_s_cmp_init");
1534 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1535 
1536 	schema->fields_info = i_s_cmp_fields_info;
1537 	schema->fill_table = i_s_cmp_fill;
1538 
1539 	DBUG_RETURN(0);
1540 }
1541 
1542 /*******************************************************************//**
1543 Bind the dynamic table information_schema.innodb_cmp_reset.
1544 @return	0 on success */
1545 static
1546 int
i_s_cmp_reset_init(void * p)1547 i_s_cmp_reset_init(
1548 /*===============*/
1549 	void*	p)	/*!< in/out: table schema object */
1550 {
1551 	DBUG_ENTER("i_s_cmp_reset_init");
1552 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1553 
1554 	schema->fields_info = i_s_cmp_fields_info;
1555 	schema->fill_table = i_s_cmp_reset_fill;
1556 
1557 	DBUG_RETURN(0);
1558 }
1559 
1560 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmp =
1561 {
1562 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1563 	/* int */
1564 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1565 
1566 	/* pointer to type-specific plugin descriptor */
1567 	/* void* */
1568 	STRUCT_FLD(info, &i_s_info),
1569 
1570 	/* plugin name */
1571 	/* const char* */
1572 	STRUCT_FLD(name, "INNODB_CMP"),
1573 
1574 	/* plugin author (for SHOW PLUGINS) */
1575 	/* const char* */
1576 	STRUCT_FLD(author, plugin_author),
1577 
1578 	/* general descriptive text (for SHOW PLUGINS) */
1579 	/* const char* */
1580 	STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
1581 
1582 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1583 	/* int */
1584 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1585 
1586 	/* the function to invoke when plugin is loaded */
1587 	/* int (*)(void*); */
1588 	STRUCT_FLD(init, i_s_cmp_init),
1589 
1590 	/* the function to invoke when plugin is unloaded */
1591 	/* int (*)(void*); */
1592 	STRUCT_FLD(deinit, i_s_common_deinit),
1593 
1594 	/* plugin version (for SHOW PLUGINS) */
1595 	/* unsigned int */
1596 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1597 
1598 	/* struct st_mysql_show_var* */
1599 	STRUCT_FLD(status_vars, NULL),
1600 
1601 	/* struct st_mysql_sys_var** */
1602 	STRUCT_FLD(system_vars, NULL),
1603 
1604 	/* reserved for dependency checking */
1605 	/* void* */
1606 	STRUCT_FLD(__reserved1, NULL),
1607 
1608 	/* Plugin flags */
1609 	/* unsigned long */
1610 	STRUCT_FLD(flags, 0UL),
1611 };
1612 
1613 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmp_reset =
1614 {
1615 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1616 	/* int */
1617 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1618 
1619 	/* pointer to type-specific plugin descriptor */
1620 	/* void* */
1621 	STRUCT_FLD(info, &i_s_info),
1622 
1623 	/* plugin name */
1624 	/* const char* */
1625 	STRUCT_FLD(name, "INNODB_CMP_RESET"),
1626 
1627 	/* plugin author (for SHOW PLUGINS) */
1628 	/* const char* */
1629 	STRUCT_FLD(author, plugin_author),
1630 
1631 	/* general descriptive text (for SHOW PLUGINS) */
1632 	/* const char* */
1633 	STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
1634 		   " reset cumulated counts"),
1635 
1636 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1637 	/* int */
1638 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1639 
1640 	/* the function to invoke when plugin is loaded */
1641 	/* int (*)(void*); */
1642 	STRUCT_FLD(init, i_s_cmp_reset_init),
1643 
1644 	/* the function to invoke when plugin is unloaded */
1645 	/* int (*)(void*); */
1646 	STRUCT_FLD(deinit, i_s_common_deinit),
1647 
1648 	/* plugin version (for SHOW PLUGINS) */
1649 	/* unsigned int */
1650 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1651 
1652 	/* struct st_mysql_show_var* */
1653 	STRUCT_FLD(status_vars, NULL),
1654 
1655 	/* struct st_mysql_sys_var** */
1656 	STRUCT_FLD(system_vars, NULL),
1657 
1658 	/* reserved for dependency checking */
1659 	/* void* */
1660 	STRUCT_FLD(__reserved1, NULL),
1661 
1662 	/* Plugin flags */
1663 	/* unsigned long */
1664 	STRUCT_FLD(flags, 0UL),
1665 };
1666 
1667 /* Fields of the dynamic tables
1668 information_schema.innodb_cmp_per_index and
1669 information_schema.innodb_cmp_per_index_reset. */
1670 static ST_FIELD_INFO	i_s_cmp_per_index_fields_info[] =
1671 {
1672 #define IDX_DATABASE_NAME	0
1673 	{STRUCT_FLD(field_name,		"database_name"),
1674 	 STRUCT_FLD(field_length,	192),
1675 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1676 	 STRUCT_FLD(value,		0),
1677 	 STRUCT_FLD(field_flags,	0),
1678 	 STRUCT_FLD(old_name,		""),
1679 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1680 
1681 #define IDX_TABLE_NAME		1
1682 	{STRUCT_FLD(field_name,		"table_name"),
1683 	 STRUCT_FLD(field_length,	192),
1684 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1685 	 STRUCT_FLD(value,		0),
1686 	 STRUCT_FLD(field_flags,	0),
1687 	 STRUCT_FLD(old_name,		""),
1688 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1689 
1690 #define IDX_INDEX_NAME		2
1691 	{STRUCT_FLD(field_name,		"index_name"),
1692 	 STRUCT_FLD(field_length,	192),
1693 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
1694 	 STRUCT_FLD(value,		0),
1695 	 STRUCT_FLD(field_flags,	0),
1696 	 STRUCT_FLD(old_name,		""),
1697 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1698 
1699 #define IDX_COMPRESS_OPS	3
1700 	{STRUCT_FLD(field_name,		"compress_ops"),
1701 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1702 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1703 	 STRUCT_FLD(value,		0),
1704 	 STRUCT_FLD(field_flags,	0),
1705 	 STRUCT_FLD(old_name,		""),
1706 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1707 
1708 #define IDX_COMPRESS_OPS_OK	4
1709 	{STRUCT_FLD(field_name,		"compress_ops_ok"),
1710 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1711 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1712 	 STRUCT_FLD(value,		0),
1713 	 STRUCT_FLD(field_flags,	0),
1714 	 STRUCT_FLD(old_name,		""),
1715 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1716 
1717 #define IDX_COMPRESS_TIME	5
1718 	{STRUCT_FLD(field_name,		"compress_time"),
1719 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1720 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1721 	 STRUCT_FLD(value,		0),
1722 	 STRUCT_FLD(field_flags,	0),
1723 	 STRUCT_FLD(old_name,		""),
1724 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1725 
1726 #define IDX_UNCOMPRESS_OPS	6
1727 	{STRUCT_FLD(field_name,		"uncompress_ops"),
1728 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1729 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1730 	 STRUCT_FLD(value,		0),
1731 	 STRUCT_FLD(field_flags,	0),
1732 	 STRUCT_FLD(old_name,		""),
1733 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1734 
1735 #define IDX_UNCOMPRESS_TIME	7
1736 	{STRUCT_FLD(field_name,		"uncompress_time"),
1737 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
1738 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
1739 	 STRUCT_FLD(value,		0),
1740 	 STRUCT_FLD(field_flags,	0),
1741 	 STRUCT_FLD(old_name,		""),
1742 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
1743 
1744 	END_OF_ST_FIELD_INFO
1745 };
1746 
1747 /*******************************************************************//**
1748 Fill the dynamic table
1749 information_schema.innodb_cmp_per_index or
1750 information_schema.innodb_cmp_per_index_reset.
1751 @return	0 on success, 1 on failure */
1752 static
1753 int
i_s_cmp_per_index_fill_low(THD * thd,TABLE_LIST * tables,Item *,ibool reset)1754 i_s_cmp_per_index_fill_low(
1755 /*=======================*/
1756 	THD*		thd,	/*!< in: thread */
1757 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1758 	Item*		,	/*!< in: condition (ignored) */
1759 	ibool		reset)	/*!< in: TRUE=reset cumulated counts */
1760 {
1761 	TABLE*	table = tables->table;
1762 	Field**	fields = table->field;
1763 	int	status = 0;
1764 
1765 	DBUG_ENTER("i_s_cmp_per_index_fill_low");
1766 
1767 	/* deny access to non-superusers */
1768 	if (check_global_access(thd, PROCESS_ACL)) {
1769 
1770 		DBUG_RETURN(0);
1771 	}
1772 
1773 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
1774 
1775 	/* Create a snapshot of the stats so we do not bump into lock
1776 	order violations with dict_sys->mutex below. */
1777 	mutex_enter(&page_zip_stat_per_index_mutex);
1778 	page_zip_stat_per_index_t		snap (page_zip_stat_per_index);
1779 	mutex_exit(&page_zip_stat_per_index_mutex);
1780 
1781 	mutex_enter(&dict_sys->mutex);
1782 
1783 	page_zip_stat_per_index_t::iterator	iter;
1784 	ulint					i;
1785 
1786 	for (iter = snap.begin(), i = 0; iter != snap.end(); iter++, i++) {
1787 
1788 		char		name[192];
1789 		dict_index_t*	index = dict_index_find_on_id_low(iter->first);
1790 
1791 		if (index != NULL) {
1792 			char	db_utf8[MAX_DB_UTF8_LEN];
1793 			char	table_utf8[MAX_TABLE_UTF8_LEN];
1794 
1795 			dict_fs2utf8(index->table_name,
1796 				     db_utf8, sizeof(db_utf8),
1797 				     table_utf8, sizeof(table_utf8));
1798 
1799 			field_store_string(fields[IDX_DATABASE_NAME], db_utf8);
1800 			field_store_string(fields[IDX_TABLE_NAME], table_utf8);
1801 			field_store_index_name(fields[IDX_INDEX_NAME],
1802 					       index->name);
1803 		} else {
1804 			/* index not found */
1805 			ut_snprintf(name, sizeof(name),
1806 				    "index_id:" IB_ID_FMT, iter->first);
1807 			field_store_string(fields[IDX_DATABASE_NAME],
1808 					   "unknown");
1809 			field_store_string(fields[IDX_TABLE_NAME],
1810 					   "unknown");
1811 			field_store_string(fields[IDX_INDEX_NAME],
1812 					   name);
1813 		}
1814 
1815 		fields[IDX_COMPRESS_OPS]->store(
1816 			static_cast<double>(iter->second.compressed));
1817 
1818 		fields[IDX_COMPRESS_OPS_OK]->store(
1819 			static_cast<double>(iter->second.compressed_ok));
1820 
1821 		fields[IDX_COMPRESS_TIME]->store(
1822 			static_cast<double>(iter->second.compressed_usec / 1000000));
1823 
1824 		fields[IDX_UNCOMPRESS_OPS]->store(
1825 			static_cast<double>(iter->second.decompressed));
1826 
1827 		fields[IDX_UNCOMPRESS_TIME]->store(
1828 			static_cast<double>(iter->second.decompressed_usec / 1000000));
1829 
1830 		if (schema_table_store_record(thd, table)) {
1831 			status = 1;
1832 			break;
1833 		}
1834 
1835 		/* Release and reacquire the dict mutex to allow other
1836 		threads to proceed. This could eventually result in the
1837 		contents of INFORMATION_SCHEMA.innodb_cmp_per_index being
1838 		inconsistent, but it is an acceptable compromise. */
1839 		if (i % 1000 == 0) {
1840 			mutex_exit(&dict_sys->mutex);
1841 			mutex_enter(&dict_sys->mutex);
1842 		}
1843 	}
1844 
1845 	mutex_exit(&dict_sys->mutex);
1846 
1847 	if (reset) {
1848 		page_zip_reset_stat_per_index();
1849 	}
1850 
1851 	DBUG_RETURN(status);
1852 }
1853 
1854 /*******************************************************************//**
1855 Fill the dynamic table information_schema.innodb_cmp_per_index.
1856 @return	0 on success, 1 on failure */
1857 static
1858 int
i_s_cmp_per_index_fill(THD * thd,TABLE_LIST * tables,Item * cond)1859 i_s_cmp_per_index_fill(
1860 /*===================*/
1861 	THD*		thd,	/*!< in: thread */
1862 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1863 	Item*		cond)	/*!< in: condition (ignored) */
1864 {
1865 	return(i_s_cmp_per_index_fill_low(thd, tables, cond, FALSE));
1866 }
1867 
1868 /*******************************************************************//**
1869 Fill the dynamic table information_schema.innodb_cmp_per_index_reset.
1870 @return	0 on success, 1 on failure */
1871 static
1872 int
i_s_cmp_per_index_reset_fill(THD * thd,TABLE_LIST * tables,Item * cond)1873 i_s_cmp_per_index_reset_fill(
1874 /*=========================*/
1875 	THD*		thd,	/*!< in: thread */
1876 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
1877 	Item*		cond)	/*!< in: condition (ignored) */
1878 {
1879 	return(i_s_cmp_per_index_fill_low(thd, tables, cond, TRUE));
1880 }
1881 
1882 /*******************************************************************//**
1883 Bind the dynamic table information_schema.innodb_cmp_per_index.
1884 @return	0 on success */
1885 static
1886 int
i_s_cmp_per_index_init(void * p)1887 i_s_cmp_per_index_init(
1888 /*===================*/
1889 	void*	p)	/*!< in/out: table schema object */
1890 {
1891 	DBUG_ENTER("i_s_cmp_init");
1892 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1893 
1894 	schema->fields_info = i_s_cmp_per_index_fields_info;
1895 	schema->fill_table = i_s_cmp_per_index_fill;
1896 
1897 	DBUG_RETURN(0);
1898 }
1899 
1900 /*******************************************************************//**
1901 Bind the dynamic table information_schema.innodb_cmp_per_index_reset.
1902 @return	0 on success */
1903 static
1904 int
i_s_cmp_per_index_reset_init(void * p)1905 i_s_cmp_per_index_reset_init(
1906 /*=========================*/
1907 	void*	p)	/*!< in/out: table schema object */
1908 {
1909 	DBUG_ENTER("i_s_cmp_reset_init");
1910 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1911 
1912 	schema->fields_info = i_s_cmp_per_index_fields_info;
1913 	schema->fill_table = i_s_cmp_per_index_reset_fill;
1914 
1915 	DBUG_RETURN(0);
1916 }
1917 
1918 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmp_per_index =
1919 {
1920 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1921 	/* int */
1922 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1923 
1924 	/* pointer to type-specific plugin descriptor */
1925 	/* void* */
1926 	STRUCT_FLD(info, &i_s_info),
1927 
1928 	/* plugin name */
1929 	/* const char* */
1930 	STRUCT_FLD(name, "INNODB_CMP_PER_INDEX"),
1931 
1932 	/* plugin author (for SHOW PLUGINS) */
1933 	/* const char* */
1934 	STRUCT_FLD(author, plugin_author),
1935 
1936 	/* general descriptive text (for SHOW PLUGINS) */
1937 	/* const char* */
1938 	STRUCT_FLD(descr, "Statistics for the InnoDB compression (per index)"),
1939 
1940 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1941 	/* int */
1942 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1943 
1944 	/* the function to invoke when plugin is loaded */
1945 	/* int (*)(void*); */
1946 	STRUCT_FLD(init, i_s_cmp_per_index_init),
1947 
1948 	/* the function to invoke when plugin is unloaded */
1949 	/* int (*)(void*); */
1950 	STRUCT_FLD(deinit, i_s_common_deinit),
1951 
1952 	/* plugin version (for SHOW PLUGINS) */
1953 	/* unsigned int */
1954 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
1955 
1956 	/* struct st_mysql_show_var* */
1957 	STRUCT_FLD(status_vars, NULL),
1958 
1959 	/* struct st_mysql_sys_var** */
1960 	STRUCT_FLD(system_vars, NULL),
1961 
1962 	/* reserved for dependency checking */
1963 	/* void* */
1964 	STRUCT_FLD(__reserved1, NULL),
1965 
1966 	/* Plugin flags */
1967 	/* unsigned long */
1968 	STRUCT_FLD(flags, 0UL),
1969 };
1970 
1971 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmp_per_index_reset =
1972 {
1973 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
1974 	/* int */
1975 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
1976 
1977 	/* pointer to type-specific plugin descriptor */
1978 	/* void* */
1979 	STRUCT_FLD(info, &i_s_info),
1980 
1981 	/* plugin name */
1982 	/* const char* */
1983 	STRUCT_FLD(name, "INNODB_CMP_PER_INDEX_RESET"),
1984 
1985 	/* plugin author (for SHOW PLUGINS) */
1986 	/* const char* */
1987 	STRUCT_FLD(author, plugin_author),
1988 
1989 	/* general descriptive text (for SHOW PLUGINS) */
1990 	/* const char* */
1991 	STRUCT_FLD(descr, "Statistics for the InnoDB compression (per index);"
1992 		   " reset cumulated counts"),
1993 
1994 	/* the plugin license (PLUGIN_LICENSE_XXX) */
1995 	/* int */
1996 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
1997 
1998 	/* the function to invoke when plugin is loaded */
1999 	/* int (*)(void*); */
2000 	STRUCT_FLD(init, i_s_cmp_per_index_reset_init),
2001 
2002 	/* the function to invoke when plugin is unloaded */
2003 	/* int (*)(void*); */
2004 	STRUCT_FLD(deinit, i_s_common_deinit),
2005 
2006 	/* plugin version (for SHOW PLUGINS) */
2007 	/* unsigned int */
2008 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
2009 
2010 	/* struct st_mysql_show_var* */
2011 	STRUCT_FLD(status_vars, NULL),
2012 
2013 	/* struct st_mysql_sys_var** */
2014 	STRUCT_FLD(system_vars, NULL),
2015 
2016 	/* reserved for dependency checking */
2017 	/* void* */
2018 	STRUCT_FLD(__reserved1, NULL),
2019 
2020 	/* Plugin flags */
2021 	/* unsigned long */
2022 	STRUCT_FLD(flags, 0UL),
2023 };
2024 
2025 /* Fields of the dynamic table information_schema.innodb_cmpmem. */
2026 static ST_FIELD_INFO	i_s_cmpmem_fields_info[] =
2027 {
2028 	{STRUCT_FLD(field_name,		"page_size"),
2029 	 STRUCT_FLD(field_length,	5),
2030 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
2031 	 STRUCT_FLD(value,		0),
2032 	 STRUCT_FLD(field_flags,	0),
2033 	 STRUCT_FLD(old_name,		"Buddy Block Size"),
2034 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2035 
2036 	{STRUCT_FLD(field_name,		"buffer_pool_instance"),
2037 	STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
2038 	STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
2039 	STRUCT_FLD(value,		0),
2040 	STRUCT_FLD(field_flags,		0),
2041 	STRUCT_FLD(old_name,		"Buffer Pool Id"),
2042 	STRUCT_FLD(open_method,		SKIP_OPEN_TABLE)},
2043 
2044 	{STRUCT_FLD(field_name,		"pages_used"),
2045 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
2046 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
2047 	 STRUCT_FLD(value,		0),
2048 	 STRUCT_FLD(field_flags,	0),
2049 	 STRUCT_FLD(old_name,		"Currently in Use"),
2050 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2051 
2052 	{STRUCT_FLD(field_name,		"pages_free"),
2053 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
2054 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
2055 	 STRUCT_FLD(value,		0),
2056 	 STRUCT_FLD(field_flags,	0),
2057 	 STRUCT_FLD(old_name,		"Currently Available"),
2058 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2059 
2060 	{STRUCT_FLD(field_name,		"relocation_ops"),
2061 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2062 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2063 	 STRUCT_FLD(value,		0),
2064 	 STRUCT_FLD(field_flags,	0),
2065 	 STRUCT_FLD(old_name,		"Total Number of Relocations"),
2066 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2067 
2068 	{STRUCT_FLD(field_name,		"relocation_time"),
2069 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
2070 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
2071 	 STRUCT_FLD(value,		0),
2072 	 STRUCT_FLD(field_flags,	0),
2073 	 STRUCT_FLD(old_name,		"Total Duration of Relocations,"
2074 					" in Seconds"),
2075 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2076 
2077 	END_OF_ST_FIELD_INFO
2078 };
2079 
2080 /*******************************************************************//**
2081 Fill the dynamic table information_schema.innodb_cmpmem or
2082 innodb_cmpmem_reset.
2083 @return	0 on success, 1 on failure */
2084 static
2085 int
i_s_cmpmem_fill_low(THD * thd,TABLE_LIST * tables,Item *,ibool reset)2086 i_s_cmpmem_fill_low(
2087 /*================*/
2088 	THD*		thd,	/*!< in: thread */
2089 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
2090 	Item*		,	/*!< in: condition (ignored) */
2091 	ibool		reset)	/*!< in: TRUE=reset cumulated counts */
2092 {
2093 	int		status = 0;
2094 	TABLE*	table	= (TABLE*) tables->table;
2095 
2096 	DBUG_ENTER("i_s_cmpmem_fill_low");
2097 
2098 	/* deny access to non-superusers */
2099 	if (check_global_access(thd, PROCESS_ACL)) {
2100 
2101 		DBUG_RETURN(0);
2102 	}
2103 
2104 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
2105 
2106 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
2107 		buf_pool_t*	buf_pool;
2108 
2109 		status	= 0;
2110 
2111 		buf_pool = buf_pool_from_array(i);
2112 
2113 		buf_pool_mutex_enter(buf_pool);
2114 
2115 		for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
2116 			buf_buddy_stat_t*	buddy_stat;
2117 
2118 			buddy_stat = &buf_pool->buddy_stat[x];
2119 
2120 			table->field[0]->store(BUF_BUDDY_LOW << x);
2121 			table->field[1]->store(static_cast<double>(i));
2122 			table->field[2]->store(static_cast<double>(
2123 				buddy_stat->used));
2124 			table->field[3]->store(static_cast<double>(
2125 				(x < BUF_BUDDY_SIZES)
2126 				? UT_LIST_GET_LEN(buf_pool->zip_free[x])
2127 				: 0));
2128 			table->field[4]->store(
2129 				(longlong) buddy_stat->relocated, true);
2130 			table->field[5]->store(
2131 				static_cast<double>(buddy_stat->relocated_usec / 1000000));
2132 
2133 			if (reset) {
2134 				/* This is protected by buf_pool->mutex. */
2135 				buddy_stat->relocated = 0;
2136 				buddy_stat->relocated_usec = 0;
2137 			}
2138 
2139 			if (schema_table_store_record(thd, table)) {
2140 				status = 1;
2141 				break;
2142 			}
2143 		}
2144 
2145 		buf_pool_mutex_exit(buf_pool);
2146 
2147 		if (status) {
2148 			break;
2149 		}
2150 	}
2151 
2152 	DBUG_RETURN(status);
2153 }
2154 
2155 /*******************************************************************//**
2156 Fill the dynamic table information_schema.innodb_cmpmem.
2157 @return	0 on success, 1 on failure */
2158 static
2159 int
i_s_cmpmem_fill(THD * thd,TABLE_LIST * tables,Item * cond)2160 i_s_cmpmem_fill(
2161 /*============*/
2162 	THD*		thd,	/*!< in: thread */
2163 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
2164 	Item*		cond)	/*!< in: condition (ignored) */
2165 {
2166 	return(i_s_cmpmem_fill_low(thd, tables, cond, FALSE));
2167 }
2168 
2169 /*******************************************************************//**
2170 Fill the dynamic table information_schema.innodb_cmpmem_reset.
2171 @return	0 on success, 1 on failure */
2172 static
2173 int
i_s_cmpmem_reset_fill(THD * thd,TABLE_LIST * tables,Item * cond)2174 i_s_cmpmem_reset_fill(
2175 /*==================*/
2176 	THD*		thd,	/*!< in: thread */
2177 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
2178 	Item*		cond)	/*!< in: condition (ignored) */
2179 {
2180 	return(i_s_cmpmem_fill_low(thd, tables, cond, TRUE));
2181 }
2182 
2183 /*******************************************************************//**
2184 Bind the dynamic table information_schema.innodb_cmpmem.
2185 @return	0 on success */
2186 static
2187 int
i_s_cmpmem_init(void * p)2188 i_s_cmpmem_init(
2189 /*============*/
2190 	void*	p)	/*!< in/out: table schema object */
2191 {
2192 	DBUG_ENTER("i_s_cmpmem_init");
2193 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
2194 
2195 	schema->fields_info = i_s_cmpmem_fields_info;
2196 	schema->fill_table = i_s_cmpmem_fill;
2197 
2198 	DBUG_RETURN(0);
2199 }
2200 
2201 /*******************************************************************//**
2202 Bind the dynamic table information_schema.innodb_cmpmem_reset.
2203 @return	0 on success */
2204 static
2205 int
i_s_cmpmem_reset_init(void * p)2206 i_s_cmpmem_reset_init(
2207 /*==================*/
2208 	void*	p)	/*!< in/out: table schema object */
2209 {
2210 	DBUG_ENTER("i_s_cmpmem_reset_init");
2211 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
2212 
2213 	schema->fields_info = i_s_cmpmem_fields_info;
2214 	schema->fill_table = i_s_cmpmem_reset_fill;
2215 
2216 	DBUG_RETURN(0);
2217 }
2218 
2219 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmpmem =
2220 {
2221 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
2222 	/* int */
2223 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2224 
2225 	/* pointer to type-specific plugin descriptor */
2226 	/* void* */
2227 	STRUCT_FLD(info, &i_s_info),
2228 
2229 	/* plugin name */
2230 	/* const char* */
2231 	STRUCT_FLD(name, "INNODB_CMPMEM"),
2232 
2233 	/* plugin author (for SHOW PLUGINS) */
2234 	/* const char* */
2235 	STRUCT_FLD(author, plugin_author),
2236 
2237 	/* general descriptive text (for SHOW PLUGINS) */
2238 	/* const char* */
2239 	STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
2240 
2241 	/* the plugin license (PLUGIN_LICENSE_XXX) */
2242 	/* int */
2243 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2244 
2245 	/* the function to invoke when plugin is loaded */
2246 	/* int (*)(void*); */
2247 	STRUCT_FLD(init, i_s_cmpmem_init),
2248 
2249 	/* the function to invoke when plugin is unloaded */
2250 	/* int (*)(void*); */
2251 	STRUCT_FLD(deinit, i_s_common_deinit),
2252 
2253 	/* plugin version (for SHOW PLUGINS) */
2254 	/* unsigned int */
2255 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
2256 
2257 	/* struct st_mysql_show_var* */
2258 	STRUCT_FLD(status_vars, NULL),
2259 
2260 	/* struct st_mysql_sys_var** */
2261 	STRUCT_FLD(system_vars, NULL),
2262 
2263 	/* reserved for dependency checking */
2264 	/* void* */
2265 	STRUCT_FLD(__reserved1, NULL),
2266 
2267 	/* Plugin flags */
2268 	/* unsigned long */
2269 	STRUCT_FLD(flags, 0UL),
2270 };
2271 
2272 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_cmpmem_reset =
2273 {
2274 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
2275 	/* int */
2276 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2277 
2278 	/* pointer to type-specific plugin descriptor */
2279 	/* void* */
2280 	STRUCT_FLD(info, &i_s_info),
2281 
2282 	/* plugin name */
2283 	/* const char* */
2284 	STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
2285 
2286 	/* plugin author (for SHOW PLUGINS) */
2287 	/* const char* */
2288 	STRUCT_FLD(author, plugin_author),
2289 
2290 	/* general descriptive text (for SHOW PLUGINS) */
2291 	/* const char* */
2292 	STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
2293 		   " reset cumulated counts"),
2294 
2295 	/* the plugin license (PLUGIN_LICENSE_XXX) */
2296 	/* int */
2297 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2298 
2299 	/* the function to invoke when plugin is loaded */
2300 	/* int (*)(void*); */
2301 	STRUCT_FLD(init, i_s_cmpmem_reset_init),
2302 
2303 	/* the function to invoke when plugin is unloaded */
2304 	/* int (*)(void*); */
2305 	STRUCT_FLD(deinit, i_s_common_deinit),
2306 
2307 	/* plugin version (for SHOW PLUGINS) */
2308 	/* unsigned int */
2309 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
2310 
2311 	/* struct st_mysql_show_var* */
2312 	STRUCT_FLD(status_vars, NULL),
2313 
2314 	/* struct st_mysql_sys_var** */
2315 	STRUCT_FLD(system_vars, NULL),
2316 
2317 	/* reserved for dependency checking */
2318 	/* void* */
2319 	STRUCT_FLD(__reserved1, NULL),
2320 
2321 	/* Plugin flags */
2322 	/* unsigned long */
2323 	STRUCT_FLD(flags, 0UL),
2324 };
2325 
2326 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_metrics */
2327 static ST_FIELD_INFO	innodb_metrics_fields_info[] =
2328 {
2329 #define	METRIC_NAME		0
2330 	{STRUCT_FLD(field_name,		"NAME"),
2331 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
2332 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2333 	 STRUCT_FLD(value,		0),
2334 	 STRUCT_FLD(field_flags,	0),
2335 	 STRUCT_FLD(old_name,		""),
2336 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2337 
2338 #define	METRIC_SUBSYS		1
2339 	{STRUCT_FLD(field_name,		"SUBSYSTEM"),
2340 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
2341 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2342 	 STRUCT_FLD(value,		0),
2343 	 STRUCT_FLD(field_flags,	0),
2344 	 STRUCT_FLD(old_name,		""),
2345 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2346 
2347 #define	METRIC_VALUE_START	2
2348 	{STRUCT_FLD(field_name,		"COUNT"),
2349 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2350 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2351 	 STRUCT_FLD(value,		0),
2352 	 STRUCT_FLD(field_flags,	0),
2353 	 STRUCT_FLD(old_name,		""),
2354 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2355 
2356 #define	METRIC_MAX_VALUE_START	3
2357 	{STRUCT_FLD(field_name,		"MAX_COUNT"),
2358 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2359 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2360 	 STRUCT_FLD(value,		0),
2361 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2362 	 STRUCT_FLD(old_name,		""),
2363 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2364 
2365 #define	METRIC_MIN_VALUE_START	4
2366 	{STRUCT_FLD(field_name,		"MIN_COUNT"),
2367 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2368 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2369 	 STRUCT_FLD(value,		0),
2370 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2371 	 STRUCT_FLD(old_name,		""),
2372 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2373 
2374 #define	METRIC_AVG_VALUE_START	5
2375 	{STRUCT_FLD(field_name,		"AVG_COUNT"),
2376 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2377 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2378 	 STRUCT_FLD(value,		0),
2379 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2380 	 STRUCT_FLD(old_name,		""),
2381 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2382 
2383 #define	METRIC_VALUE_RESET	6
2384 	{STRUCT_FLD(field_name,		"COUNT_RESET"),
2385 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2386 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2387 	 STRUCT_FLD(value,		0),
2388 	 STRUCT_FLD(field_flags,	0),
2389 	 STRUCT_FLD(old_name,		""),
2390 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2391 
2392 #define	METRIC_MAX_VALUE_RESET	7
2393 	{STRUCT_FLD(field_name,		"MAX_COUNT_RESET"),
2394 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2395 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2396 	 STRUCT_FLD(value,		0),
2397 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2398 	 STRUCT_FLD(old_name,		""),
2399 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2400 
2401 #define	METRIC_MIN_VALUE_RESET	8
2402 	{STRUCT_FLD(field_name,		"MIN_COUNT_RESET"),
2403 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2404 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2405 	 STRUCT_FLD(value,		0),
2406 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2407 	 STRUCT_FLD(old_name,		""),
2408 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2409 
2410 #define	METRIC_AVG_VALUE_RESET	9
2411 	{STRUCT_FLD(field_name,		"AVG_COUNT_RESET"),
2412 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
2413 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
2414 	 STRUCT_FLD(value,		0),
2415 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2416 	 STRUCT_FLD(old_name,		""),
2417 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2418 
2419 #define	METRIC_START_TIME	10
2420 	{STRUCT_FLD(field_name,		"TIME_ENABLED"),
2421 	 STRUCT_FLD(field_length,	0),
2422 	 STRUCT_FLD(field_type,		MYSQL_TYPE_DATETIME),
2423 	 STRUCT_FLD(value,		0),
2424 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2425 	 STRUCT_FLD(old_name,		""),
2426 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2427 
2428 #define	METRIC_STOP_TIME	11
2429 	{STRUCT_FLD(field_name,		"TIME_DISABLED"),
2430 	 STRUCT_FLD(field_length,	0),
2431 	 STRUCT_FLD(field_type,		MYSQL_TYPE_DATETIME),
2432 	 STRUCT_FLD(value,		0),
2433 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2434 	 STRUCT_FLD(old_name,		""),
2435 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2436 
2437 #define	METRIC_TIME_ELAPSED	12
2438 	{STRUCT_FLD(field_name,		"TIME_ELAPSED"),
2439 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2440 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2441 	 STRUCT_FLD(value,		0),
2442 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2443 	 STRUCT_FLD(old_name,		""),
2444 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2445 
2446 #define	METRIC_RESET_TIME	13
2447 	{STRUCT_FLD(field_name,		"TIME_RESET"),
2448 	 STRUCT_FLD(field_length,	0),
2449 	 STRUCT_FLD(field_type,		MYSQL_TYPE_DATETIME),
2450 	 STRUCT_FLD(value,		0),
2451 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
2452 	 STRUCT_FLD(old_name,		""),
2453 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2454 
2455 #define	METRIC_STATUS		14
2456 	{STRUCT_FLD(field_name,		"STATUS"),
2457 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
2458 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2459 	 STRUCT_FLD(value,		0),
2460 	 STRUCT_FLD(field_flags,	0),
2461 	 STRUCT_FLD(old_name,		""),
2462 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2463 
2464 #define	METRIC_TYPE		15
2465 	{STRUCT_FLD(field_name,		"TYPE"),
2466 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
2467 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2468 	 STRUCT_FLD(value,		0),
2469 	 STRUCT_FLD(field_flags,	0),
2470 	 STRUCT_FLD(old_name,		""),
2471 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2472 
2473 #define	METRIC_DESC		16
2474 	{STRUCT_FLD(field_name,		"COMMENT"),
2475 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
2476 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2477 	 STRUCT_FLD(value,		0),
2478 	 STRUCT_FLD(field_flags,	0),
2479 	 STRUCT_FLD(old_name,		""),
2480 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2481 
2482 	END_OF_ST_FIELD_INFO
2483 };
2484 
2485 /**********************************************************************//**
2486 Fill the information schema metrics table.
2487 @return	0 on success */
2488 static
2489 int
i_s_metrics_fill(THD * thd,TABLE * table_to_fill)2490 i_s_metrics_fill(
2491 /*=============*/
2492 	THD*		thd,		/*!< in: thread */
2493 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
2494 {
2495 	int		count;
2496 	Field**		fields;
2497 	double		time_diff = 0;
2498 	monitor_info_t*	monitor_info;
2499 	mon_type_t	min_val;
2500 	mon_type_t	max_val;
2501 
2502 	DBUG_ENTER("i_s_metrics_fill");
2503 	fields = table_to_fill->field;
2504 
2505 	for (count = 0; count < NUM_MONITOR; count++) {
2506 		monitor_info = srv_mon_get_info((monitor_id_t) count);
2507 
2508 		/* A good place to sanity check the Monitor ID */
2509 		ut_a(count == monitor_info->monitor_id);
2510 
2511 		/* If the item refers to a Module, nothing to fill,
2512 		continue. */
2513 		if ((monitor_info->monitor_type & MONITOR_MODULE)
2514 		    || (monitor_info->monitor_type & MONITOR_HIDDEN)) {
2515 			continue;
2516 		}
2517 
2518 		/* If this is an existing "status variable", and
2519 		its corresponding counter is still on, we need
2520 		to calculate the result from its corresponding
2521 		counter. */
2522 		if (monitor_info->monitor_type & MONITOR_EXISTING
2523 		    && MONITOR_IS_ON(count)) {
2524 			srv_mon_process_existing_counter((monitor_id_t) count,
2525 							 MONITOR_GET_VALUE);
2526 		}
2527 
2528 		/* Fill in counter's basic information */
2529 		OK(field_store_string(fields[METRIC_NAME],
2530 				      monitor_info->monitor_name));
2531 
2532 		OK(field_store_string(fields[METRIC_SUBSYS],
2533 				      monitor_info->monitor_module));
2534 
2535 		OK(field_store_string(fields[METRIC_DESC],
2536 				      monitor_info->monitor_desc));
2537 
2538 		/* Fill in counter values */
2539 		OK(fields[METRIC_VALUE_RESET]->store(
2540 			MONITOR_VALUE(count), FALSE));
2541 
2542 		OK(fields[METRIC_VALUE_START]->store(
2543 			MONITOR_VALUE_SINCE_START(count), FALSE));
2544 
2545 		/* If the max value is MAX_RESERVED, counter max
2546 		value has not been updated. Set the column value
2547 		to NULL. */
2548 		if (MONITOR_MAX_VALUE(count) == MAX_RESERVED
2549 		    || MONITOR_MAX_MIN_NOT_INIT(count)) {
2550 			fields[METRIC_MAX_VALUE_RESET]->set_null();
2551 		} else {
2552 			OK(fields[METRIC_MAX_VALUE_RESET]->store(
2553 				MONITOR_MAX_VALUE(count), FALSE));
2554 			fields[METRIC_MAX_VALUE_RESET]->set_notnull();
2555 		}
2556 
2557 		/* If the min value is MAX_RESERVED, counter min
2558 		value has not been updated. Set the column value
2559 		to NULL. */
2560 		if (MONITOR_MIN_VALUE(count) == MIN_RESERVED
2561 		    || MONITOR_MAX_MIN_NOT_INIT(count)) {
2562 			fields[METRIC_MIN_VALUE_RESET]->set_null();
2563 		} else {
2564 			OK(fields[METRIC_MIN_VALUE_RESET]->store(
2565 				MONITOR_MIN_VALUE(count), FALSE));
2566 			fields[METRIC_MIN_VALUE_RESET]->set_notnull();
2567 		}
2568 
2569 		/* Calculate the max value since counter started */
2570 		max_val = srv_mon_calc_max_since_start((monitor_id_t) count);
2571 
2572 		if (max_val == MAX_RESERVED
2573 		    || MONITOR_MAX_MIN_NOT_INIT(count)) {
2574 			fields[METRIC_MAX_VALUE_START]->set_null();
2575 		} else {
2576 			OK(fields[METRIC_MAX_VALUE_START]->store(
2577 				max_val, FALSE));
2578 			fields[METRIC_MAX_VALUE_START]->set_notnull();
2579 		}
2580 
2581 		/* Calculate the min value since counter started */
2582 		min_val = srv_mon_calc_min_since_start((monitor_id_t) count);
2583 
2584 		if (min_val == MIN_RESERVED
2585 		    || MONITOR_MAX_MIN_NOT_INIT(count)) {
2586 			fields[METRIC_MIN_VALUE_START]->set_null();
2587 		} else {
2588 			OK(fields[METRIC_MIN_VALUE_START]->store(
2589 				min_val, FALSE));
2590 
2591 			fields[METRIC_MIN_VALUE_START]->set_notnull();
2592 		}
2593 
2594 		/* If monitor has been enabled (no matter it is disabled
2595 		or not now), fill METRIC_START_TIME and METRIC_TIME_ELAPSED
2596 		field */
2597 		if (MONITOR_FIELD(count, mon_start_time)) {
2598 			OK(field_store_time_t(fields[METRIC_START_TIME],
2599 				(time_t)MONITOR_FIELD(count, mon_start_time)));
2600 			fields[METRIC_START_TIME]->set_notnull();
2601 
2602 			/* If monitor is enabled, the TIME_ELAPSED is the
2603 			time difference between current and time when monitor
2604 			is enabled. Otherwise, it is the time difference
2605 			between time when monitor is enabled and time
2606 			when it is disabled */
2607 			if (MONITOR_IS_ON(count)) {
2608 				time_diff = difftime(time(NULL),
2609 					MONITOR_FIELD(count, mon_start_time));
2610 			} else {
2611 				time_diff =  difftime(
2612 					MONITOR_FIELD(count, mon_stop_time),
2613 					MONITOR_FIELD(count, mon_start_time));
2614 			}
2615 
2616 			OK(fields[METRIC_TIME_ELAPSED]->store(
2617 				time_diff));
2618 			fields[METRIC_TIME_ELAPSED]->set_notnull();
2619 		} else {
2620 			fields[METRIC_START_TIME]->set_null();
2621 			fields[METRIC_TIME_ELAPSED]->set_null();
2622 			time_diff = 0;
2623 		}
2624 
2625 		/* Unless MONITOR__NO_AVERAGE is marked, we will need
2626 		to calculate the average value. If this is a monitor set
2627 		owner marked by MONITOR_SET_OWNER, divide
2628 		the value by another counter (number of calls) designated
2629 		by monitor_info->monitor_related_id.
2630 		Otherwise average the counter value by the time between the
2631 		time that the counter is enabled and time it is disabled
2632 		or time it is sampled. */
2633 		if (!(monitor_info->monitor_type & MONITOR_NO_AVERAGE)
2634 		    && (monitor_info->monitor_type & MONITOR_SET_OWNER)
2635 		    && monitor_info->monitor_related_id) {
2636 			mon_type_t	value_start
2637 				 = MONITOR_VALUE_SINCE_START(
2638 					monitor_info->monitor_related_id);
2639 
2640 			if (value_start) {
2641 				OK(fields[METRIC_AVG_VALUE_START]->store(
2642 					MONITOR_VALUE_SINCE_START(count)
2643 					/ value_start, FALSE));
2644 
2645 				fields[METRIC_AVG_VALUE_START]->set_notnull();
2646 			} else {
2647 				fields[METRIC_AVG_VALUE_START]->set_null();
2648 			}
2649 
2650 			if (MONITOR_VALUE(monitor_info->monitor_related_id)) {
2651 				OK(fields[METRIC_AVG_VALUE_RESET]->store(
2652 					MONITOR_VALUE(count)
2653 					/ MONITOR_VALUE(
2654 					monitor_info->monitor_related_id),
2655 					FALSE));
2656 			} else {
2657 				fields[METRIC_AVG_VALUE_RESET]->set_null();
2658 			}
2659 		} else if (!(monitor_info->monitor_type & MONITOR_NO_AVERAGE)
2660 			   && !(monitor_info->monitor_type
2661 				& MONITOR_DISPLAY_CURRENT)) {
2662 			if (time_diff) {
2663 				OK(fields[METRIC_AVG_VALUE_START]->store(
2664 					(double) MONITOR_VALUE_SINCE_START(
2665 						count) / time_diff));
2666 				fields[METRIC_AVG_VALUE_START]->set_notnull();
2667 			} else {
2668 				fields[METRIC_AVG_VALUE_START]->set_null();
2669 			}
2670 
2671 			if (MONITOR_FIELD(count, mon_reset_time)) {
2672 				/* calculate the time difference since last
2673 				reset */
2674 				if (MONITOR_IS_ON(count)) {
2675 					time_diff = difftime(
2676 						time(NULL), MONITOR_FIELD(
2677 							count, mon_reset_time));
2678 				} else {
2679 					time_diff =  difftime(
2680 					MONITOR_FIELD(count, mon_stop_time),
2681 					MONITOR_FIELD(count, mon_reset_time));
2682 				}
2683 			} else {
2684 				time_diff = 0;
2685 			}
2686 
2687 			if (time_diff) {
2688 				OK(fields[METRIC_AVG_VALUE_RESET]->store(
2689 					static_cast<double>(
2690 						MONITOR_VALUE(count) / time_diff)));
2691 				fields[METRIC_AVG_VALUE_RESET]->set_notnull();
2692 			} else {
2693 				fields[METRIC_AVG_VALUE_RESET]->set_null();
2694 			}
2695 		} else {
2696 			fields[METRIC_AVG_VALUE_START]->set_null();
2697 			fields[METRIC_AVG_VALUE_RESET]->set_null();
2698 		}
2699 
2700 
2701 		if (MONITOR_IS_ON(count)) {
2702 			/* If monitor is on, the stop time will set to NULL */
2703 			fields[METRIC_STOP_TIME]->set_null();
2704 
2705 			/* Display latest Monitor Reset Time only if Monitor
2706 			counter is on. */
2707 			if (MONITOR_FIELD(count, mon_reset_time)) {
2708 				OK(field_store_time_t(
2709 					fields[METRIC_RESET_TIME],
2710 					(time_t)MONITOR_FIELD(
2711 						count, mon_reset_time)));
2712 				fields[METRIC_RESET_TIME]->set_notnull();
2713 			} else {
2714 				fields[METRIC_RESET_TIME]->set_null();
2715 			}
2716 
2717 			/* Display the monitor status as "enabled" */
2718 			OK(field_store_string(fields[METRIC_STATUS],
2719 					      "enabled"));
2720 		} else {
2721 			if (MONITOR_FIELD(count, mon_stop_time)) {
2722 				OK(field_store_time_t(fields[METRIC_STOP_TIME],
2723 				(time_t)MONITOR_FIELD(count, mon_stop_time)));
2724 				fields[METRIC_STOP_TIME]->set_notnull();
2725 			} else {
2726 				fields[METRIC_STOP_TIME]->set_null();
2727 			}
2728 
2729 			fields[METRIC_RESET_TIME]->set_null();
2730 
2731 			OK(field_store_string(fields[METRIC_STATUS],
2732 					      "disabled"));
2733 		}
2734 
2735 		if (monitor_info->monitor_type & MONITOR_DISPLAY_CURRENT) {
2736 			OK(field_store_string(fields[METRIC_TYPE],
2737 					      "value"));
2738 		} else if (monitor_info->monitor_type & MONITOR_EXISTING) {
2739 			OK(field_store_string(fields[METRIC_TYPE],
2740 					      "status_counter"));
2741 		} else if (monitor_info->monitor_type & MONITOR_SET_OWNER) {
2742 			OK(field_store_string(fields[METRIC_TYPE],
2743 					      "set_owner"));
2744 		} else if ( monitor_info->monitor_type & MONITOR_SET_MEMBER) {
2745 			OK(field_store_string(fields[METRIC_TYPE],
2746 					      "set_member"));
2747 		} else {
2748 			OK(field_store_string(fields[METRIC_TYPE],
2749 					      "counter"));
2750 		}
2751 
2752 		OK(schema_table_store_record(thd, table_to_fill));
2753 	}
2754 
2755 	DBUG_RETURN(0);
2756 }
2757 
2758 /*******************************************************************//**
2759 Function to fill information schema metrics tables.
2760 @return	0 on success */
2761 static
2762 int
i_s_metrics_fill_table(THD * thd,TABLE_LIST * tables,Item *)2763 i_s_metrics_fill_table(
2764 /*===================*/
2765 	THD*		thd,	/*!< in: thread */
2766 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
2767 	Item*		)	/*!< in: condition (not used) */
2768 {
2769 	DBUG_ENTER("i_s_metrics_fill_table");
2770 
2771 	/* deny access to non-superusers */
2772 	if (check_global_access(thd, PROCESS_ACL)) {
2773 		DBUG_RETURN(0);
2774 	}
2775 
2776 	i_s_metrics_fill(thd, tables->table);
2777 
2778 	DBUG_RETURN(0);
2779 }
2780 /*******************************************************************//**
2781 Bind the dynamic table INFORMATION_SCHEMA.innodb_metrics
2782 @return	0 on success */
2783 static
2784 int
innodb_metrics_init(void * p)2785 innodb_metrics_init(
2786 /*================*/
2787 	void*	p)	/*!< in/out: table schema object */
2788 {
2789 	ST_SCHEMA_TABLE*	schema;
2790 
2791 	DBUG_ENTER("innodb_metrics_init");
2792 
2793 	schema = (ST_SCHEMA_TABLE*) p;
2794 
2795 	schema->fields_info = innodb_metrics_fields_info;
2796 	schema->fill_table = i_s_metrics_fill_table;
2797 
2798 	DBUG_RETURN(0);
2799 }
2800 
2801 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_metrics =
2802 {
2803 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
2804 	/* int */
2805 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2806 
2807 	/* pointer to type-specific plugin descriptor */
2808 	/* void* */
2809 	STRUCT_FLD(info, &i_s_info),
2810 
2811 	/* plugin name */
2812 	/* const char* */
2813 	STRUCT_FLD(name, "INNODB_METRICS"),
2814 
2815 	/* plugin author (for SHOW PLUGINS) */
2816 	/* const char* */
2817 	STRUCT_FLD(author, plugin_author),
2818 
2819 	/* general descriptive text (for SHOW PLUGINS) */
2820 	/* const char* */
2821 	STRUCT_FLD(descr, "InnoDB Metrics Info"),
2822 
2823 	/* the plugin license (PLUGIN_LICENSE_XXX) */
2824 	/* int */
2825 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2826 
2827 	/* the function to invoke when plugin is loaded */
2828 	/* int (*)(void*); */
2829 	STRUCT_FLD(init, innodb_metrics_init),
2830 
2831 	/* the function to invoke when plugin is unloaded */
2832 	/* int (*)(void*); */
2833 	STRUCT_FLD(deinit, i_s_common_deinit),
2834 
2835 	/* plugin version (for SHOW PLUGINS) */
2836 	/* unsigned int */
2837 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
2838 
2839 	/* struct st_mysql_show_var* */
2840 	STRUCT_FLD(status_vars, NULL),
2841 
2842 	/* struct st_mysql_sys_var** */
2843 	STRUCT_FLD(system_vars, NULL),
2844 
2845 	/* reserved for dependency checking */
2846 	/* void* */
2847 	STRUCT_FLD(__reserved1, NULL),
2848 
2849 	/* Plugin flags */
2850 	/* unsigned long */
2851 	STRUCT_FLD(flags, 0UL),
2852 };
2853 /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_ft_default_stopword */
2854 static ST_FIELD_INFO	i_s_stopword_fields_info[] =
2855 {
2856 #define STOPWORD_VALUE	0
2857 	{STRUCT_FLD(field_name,		"value"),
2858 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
2859 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
2860 	 STRUCT_FLD(value,		0),
2861 	 STRUCT_FLD(field_flags,	0),
2862 	 STRUCT_FLD(old_name,		""),
2863 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2864 
2865 	END_OF_ST_FIELD_INFO
2866 };
2867 
2868 /*******************************************************************//**
2869 Fill the dynamic table information_schema.innodb_ft_default_stopword.
2870 @return	0 on success, 1 on failure */
2871 static
2872 int
i_s_stopword_fill(THD * thd,TABLE_LIST * tables,Item *)2873 i_s_stopword_fill(
2874 /*==============*/
2875 	THD*		thd,	/*!< in: thread */
2876 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
2877 	Item*		)	/*!< in: condition (not used) */
2878 {
2879 	Field**	fields;
2880 	ulint	i = 0;
2881 	TABLE*	table = (TABLE*) tables->table;
2882 
2883 	DBUG_ENTER("i_s_stopword_fill");
2884 
2885 	fields = table->field;
2886 
2887 	/* Fill with server default stopword list in array
2888 	fts_default_stopword */
2889 	while (fts_default_stopword[i]) {
2890 		OK(field_store_string(fields[STOPWORD_VALUE],
2891 				      fts_default_stopword[i]));
2892 
2893 		OK(schema_table_store_record(thd, table));
2894 		i++;
2895 	}
2896 
2897 	DBUG_RETURN(0);
2898 }
2899 
2900 /*******************************************************************//**
2901 Bind the dynamic table information_schema.innodb_ft_default_stopword.
2902 @return	0 on success */
2903 static
2904 int
i_s_stopword_init(void * p)2905 i_s_stopword_init(
2906 /*==============*/
2907 	void*	p)	/*!< in/out: table schema object */
2908 {
2909 	DBUG_ENTER("i_s_stopword_init");
2910 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
2911 
2912 	schema->fields_info = i_s_stopword_fields_info;
2913 	schema->fill_table = i_s_stopword_fill;
2914 
2915 	DBUG_RETURN(0);
2916 }
2917 
2918 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_ft_default_stopword =
2919 {
2920 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
2921 	/* int */
2922 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
2923 
2924 	/* pointer to type-specific plugin descriptor */
2925 	/* void* */
2926 	STRUCT_FLD(info, &i_s_info),
2927 
2928 	/* plugin name */
2929 	/* const char* */
2930 	STRUCT_FLD(name, "INNODB_FT_DEFAULT_STOPWORD"),
2931 
2932 	/* plugin author (for SHOW PLUGINS) */
2933 	/* const char* */
2934 	STRUCT_FLD(author, plugin_author),
2935 
2936 	/* general descriptive text (for SHOW PLUGINS) */
2937 	/* const char* */
2938 	STRUCT_FLD(descr, "Default stopword list for InnDB Full Text Search"),
2939 
2940 	/* the plugin license (PLUGIN_LICENSE_XXX) */
2941 	/* int */
2942 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
2943 
2944 	/* the function to invoke when plugin is loaded */
2945 	/* int (*)(void*); */
2946 	STRUCT_FLD(init, i_s_stopword_init),
2947 
2948 	/* the function to invoke when plugin is unloaded */
2949 	/* int (*)(void*); */
2950 	STRUCT_FLD(deinit, i_s_common_deinit),
2951 
2952 	/* plugin version (for SHOW PLUGINS) */
2953 	/* unsigned int */
2954 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
2955 
2956 	/* struct st_mysql_show_var* */
2957 	STRUCT_FLD(status_vars, NULL),
2958 
2959 	/* struct st_mysql_sys_var** */
2960 	STRUCT_FLD(system_vars, NULL),
2961 
2962 	/* reserved for dependency checking */
2963 	/* void* */
2964 	STRUCT_FLD(__reserved1, NULL),
2965 
2966 	/* Plugin flags */
2967 	/* unsigned long */
2968 	STRUCT_FLD(flags, 0UL),
2969 };
2970 
2971 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED
2972 INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED */
2973 static ST_FIELD_INFO	i_s_fts_doc_fields_info[] =
2974 {
2975 #define	I_S_FTS_DOC_ID			0
2976 	{STRUCT_FLD(field_name,		"DOC_ID"),
2977 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
2978 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
2979 	 STRUCT_FLD(value,		0),
2980 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
2981 	 STRUCT_FLD(old_name,		""),
2982 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
2983 
2984 	END_OF_ST_FIELD_INFO
2985 };
2986 
2987 /*******************************************************************//**
2988 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED or
2989 INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED
2990 @return	0 on success, 1 on failure */
2991 static
2992 int
i_s_fts_deleted_generic_fill(THD * thd,TABLE_LIST * tables,ibool being_deleted)2993 i_s_fts_deleted_generic_fill(
2994 /*=========================*/
2995 	THD*		thd,		/*!< in: thread */
2996 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
2997 	ibool		being_deleted)	/*!< in: BEING_DELTED table */
2998 {
2999 	Field**			fields;
3000 	TABLE*			table = (TABLE*) tables->table;
3001 	trx_t*			trx;
3002 	fts_table_t		fts_table;
3003 	fts_doc_ids_t*		deleted;
3004 	dict_table_t*		user_table;
3005 
3006 	DBUG_ENTER("i_s_fts_deleted_generic_fill");
3007 
3008 	/* deny access to non-superusers */
3009 	if (check_global_access(thd, PROCESS_ACL)) {
3010 		DBUG_RETURN(0);
3011 	}
3012 
3013 	mysql_mutex_lock(&LOCK_global_system_variables);
3014 
3015 	if (!fts_internal_tbl_name) {
3016 		mysql_mutex_unlock(&LOCK_global_system_variables);
3017 		DBUG_RETURN(0);
3018 	}
3019 
3020 	std::string fts_table_name(fts_internal_tbl_name);
3021 	mysql_mutex_unlock(&LOCK_global_system_variables);
3022 
3023 	if(!fts_table_name.c_str()) {
3024 		DBUG_RETURN(0);
3025 	}
3026 
3027 	/* Prevent DDL to drop fts aux tables. */
3028 	rw_lock_s_lock(&dict_operation_lock);
3029 
3030 	user_table = dict_table_open_on_name(
3031 		fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3032 
3033 	if (!user_table) {
3034 		rw_lock_s_unlock(&dict_operation_lock);
3035 
3036 		DBUG_RETURN(0);
3037 	} else if (!dict_table_has_fts_index(user_table)) {
3038 		dict_table_close(user_table, FALSE, FALSE);
3039 
3040 		rw_lock_s_unlock(&dict_operation_lock);
3041 
3042 		DBUG_RETURN(0);
3043 	}
3044 
3045 	deleted = fts_doc_ids_create();
3046 
3047 	trx = trx_allocate_for_background();
3048 	trx->op_info = "Select for FTS DELETE TABLE";
3049 
3050 	FTS_INIT_FTS_TABLE(&fts_table,
3051 			   (being_deleted) ? "BEING_DELETED" : "DELETED",
3052 			   FTS_COMMON_TABLE, user_table);
3053 
3054 	fts_table_fetch_doc_ids(trx, &fts_table, deleted);
3055 
3056 	fields = table->field;
3057 
3058 	for (ulint j = 0; j < ib_vector_size(deleted->doc_ids); ++j) {
3059 		doc_id_t	doc_id;
3060 
3061 		doc_id = *(doc_id_t*) ib_vector_get_const(deleted->doc_ids, j);
3062 
3063 		OK(fields[I_S_FTS_DOC_ID]->store((longlong) doc_id, true));
3064 
3065 		OK(schema_table_store_record(thd, table));
3066 	}
3067 
3068 	trx_free_for_background(trx);
3069 
3070 	fts_doc_ids_free(deleted);
3071 
3072 	dict_table_close(user_table, FALSE, FALSE);
3073 
3074 	rw_lock_s_unlock(&dict_operation_lock);
3075 
3076 	DBUG_RETURN(0);
3077 }
3078 
3079 /*******************************************************************//**
3080 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED
3081 @return	0 on success, 1 on failure */
3082 static
3083 int
i_s_fts_deleted_fill(THD * thd,TABLE_LIST * tables,Item *)3084 i_s_fts_deleted_fill(
3085 /*=================*/
3086 	THD*		thd,	/*!< in: thread */
3087 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
3088 	Item*		)	/*!< in: condition (ignored) */
3089 {
3090 	DBUG_ENTER("i_s_fts_deleted_fill");
3091 
3092 	DBUG_RETURN(i_s_fts_deleted_generic_fill(thd, tables, FALSE));
3093 }
3094 
3095 /*******************************************************************//**
3096 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_DELETED
3097 @return	0 on success */
3098 static
3099 int
i_s_fts_deleted_init(void * p)3100 i_s_fts_deleted_init(
3101 /*=================*/
3102 	void*	p)	/*!< in/out: table schema object */
3103 {
3104 	DBUG_ENTER("i_s_fts_deleted_init");
3105 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3106 
3107 	schema->fields_info = i_s_fts_doc_fields_info;
3108 	schema->fill_table = i_s_fts_deleted_fill;
3109 
3110 	DBUG_RETURN(0);
3111 }
3112 
3113 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_ft_deleted =
3114 {
3115 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3116 	/* int */
3117 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3118 
3119 	/* pointer to type-specific plugin descriptor */
3120 	/* void* */
3121 	STRUCT_FLD(info, &i_s_info),
3122 
3123 	/* plugin name */
3124 	/* const char* */
3125 	STRUCT_FLD(name, "INNODB_FT_DELETED"),
3126 
3127 	/* plugin author (for SHOW PLUGINS) */
3128 	/* const char* */
3129 	STRUCT_FLD(author, plugin_author),
3130 
3131 	/* general descriptive text (for SHOW PLUGINS) */
3132 	/* const char* */
3133 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS DELETED TABLE"),
3134 
3135 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3136 	/* int */
3137 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3138 
3139 	/* the function to invoke when plugin is loaded */
3140 	/* int (*)(void*); */
3141 	STRUCT_FLD(init, i_s_fts_deleted_init),
3142 
3143 	/* the function to invoke when plugin is unloaded */
3144 	/* int (*)(void*); */
3145 	STRUCT_FLD(deinit, i_s_common_deinit),
3146 
3147 	/* plugin version (for SHOW PLUGINS) */
3148 	/* unsigned int */
3149 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
3150 
3151 	/* struct st_mysql_show_var* */
3152 	STRUCT_FLD(status_vars, NULL),
3153 
3154 	/* struct st_mysql_sys_var** */
3155 	STRUCT_FLD(system_vars, NULL),
3156 
3157 	/* reserved for dependency checking */
3158 	/* void* */
3159 	STRUCT_FLD(__reserved1, NULL),
3160 
3161 	/* Plugin flags */
3162 	/* unsigned long */
3163 	STRUCT_FLD(flags, 0UL),
3164 };
3165 
3166 /*******************************************************************//**
3167 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED
3168 @return	0 on success, 1 on failure */
3169 static
3170 int
i_s_fts_being_deleted_fill(THD * thd,TABLE_LIST * tables,Item *)3171 i_s_fts_being_deleted_fill(
3172 /*=======================*/
3173 	THD*		thd,	/*!< in: thread */
3174 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
3175 	Item*		)	/*!< in: condition (ignored) */
3176 {
3177 	DBUG_ENTER("i_s_fts_being_deleted_fill");
3178 
3179 	DBUG_RETURN(i_s_fts_deleted_generic_fill(thd, tables, TRUE));
3180 }
3181 
3182 /*******************************************************************//**
3183 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_BEING_DELETED
3184 @return	0 on success */
3185 static
3186 int
i_s_fts_being_deleted_init(void * p)3187 i_s_fts_being_deleted_init(
3188 /*=======================*/
3189 	void*	p)	/*!< in/out: table schema object */
3190 {
3191 	DBUG_ENTER("i_s_fts_deleted_init");
3192 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3193 
3194 	schema->fields_info = i_s_fts_doc_fields_info;
3195 	schema->fill_table = i_s_fts_being_deleted_fill;
3196 
3197 	DBUG_RETURN(0);
3198 }
3199 
3200 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_ft_being_deleted =
3201 {
3202 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3203 	/* int */
3204 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3205 
3206 	/* pointer to type-specific plugin descriptor */
3207 	/* void* */
3208 	STRUCT_FLD(info, &i_s_info),
3209 
3210 	/* plugin name */
3211 	/* const char* */
3212 	STRUCT_FLD(name, "INNODB_FT_BEING_DELETED"),
3213 
3214 	/* plugin author (for SHOW PLUGINS) */
3215 	/* const char* */
3216 	STRUCT_FLD(author, plugin_author),
3217 
3218 	/* general descriptive text (for SHOW PLUGINS) */
3219 	/* const char* */
3220 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS BEING DELETED TABLE"),
3221 
3222 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3223 	/* int */
3224 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3225 
3226 	/* the function to invoke when plugin is loaded */
3227 	/* int (*)(void*); */
3228 	STRUCT_FLD(init, i_s_fts_being_deleted_init),
3229 
3230 	/* the function to invoke when plugin is unloaded */
3231 	/* int (*)(void*); */
3232 	STRUCT_FLD(deinit, i_s_common_deinit),
3233 
3234 	/* plugin version (for SHOW PLUGINS) */
3235 	/* unsigned int */
3236 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
3237 
3238 	/* struct st_mysql_show_var* */
3239 	STRUCT_FLD(status_vars, NULL),
3240 
3241 	/* struct st_mysql_sys_var** */
3242 	STRUCT_FLD(system_vars, NULL),
3243 
3244 	/* reserved for dependency checking */
3245 	/* void* */
3246 	STRUCT_FLD(__reserved1, NULL),
3247 
3248 	/* Plugin flags */
3249 	/* unsigned long */
3250 	STRUCT_FLD(flags, 0UL),
3251 };
3252 
3253 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED and
3254 INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE */
3255 static ST_FIELD_INFO	i_s_fts_index_fields_info[] =
3256 {
3257 #define	I_S_FTS_WORD			0
3258 	{STRUCT_FLD(field_name,		"WORD"),
3259 	 STRUCT_FLD(field_length,	FTS_MAX_WORD_LEN + 1),
3260 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
3261 	 STRUCT_FLD(value,		0),
3262 	 STRUCT_FLD(field_flags,	0),
3263 	 STRUCT_FLD(old_name,		""),
3264 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3265 
3266 #define	I_S_FTS_FIRST_DOC_ID		1
3267 	{STRUCT_FLD(field_name,		"FIRST_DOC_ID"),
3268 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3269 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3270 	 STRUCT_FLD(value,		0),
3271 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3272 	 STRUCT_FLD(old_name,		""),
3273 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3274 
3275 #define	I_S_FTS_LAST_DOC_ID		2
3276 	{STRUCT_FLD(field_name,		"LAST_DOC_ID"),
3277 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3278 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3279 	 STRUCT_FLD(value,		0),
3280 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3281 	 STRUCT_FLD(old_name,		""),
3282 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3283 
3284 #define	I_S_FTS_DOC_COUNT		3
3285 	{STRUCT_FLD(field_name,		"DOC_COUNT"),
3286 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3287 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3288 	 STRUCT_FLD(value,		0),
3289 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3290 	 STRUCT_FLD(old_name,		""),
3291 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3292 
3293 #define	I_S_FTS_ILIST_DOC_ID		4
3294 	{STRUCT_FLD(field_name,		"DOC_ID"),
3295 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3296 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3297 	 STRUCT_FLD(value,		0),
3298 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3299 	 STRUCT_FLD(old_name,		""),
3300 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3301 
3302 #define	I_S_FTS_ILIST_DOC_POS		5
3303 	{STRUCT_FLD(field_name,		"POSITION"),
3304 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
3305 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
3306 	 STRUCT_FLD(value,		0),
3307 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
3308 	 STRUCT_FLD(old_name,		""),
3309 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
3310 
3311 	END_OF_ST_FIELD_INFO
3312 };
3313 
3314 /*******************************************************************//**
3315 Go through the Doc Node and its ilist, fill the dynamic table
3316 INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED for one FTS index on the table.
3317 @return	0 on success, 1 on failure */
3318 static
3319 int
i_s_fts_index_cache_fill_one_index(fts_index_cache_t * index_cache,THD * thd,TABLE_LIST * tables)3320 i_s_fts_index_cache_fill_one_index(
3321 /*===============================*/
3322 	fts_index_cache_t*	index_cache,	/*!< in: FTS index cache */
3323 	THD*			thd,		/*!< in: thread */
3324 	TABLE_LIST*		tables)		/*!< in/out: tables to fill */
3325 {
3326 	TABLE*			table = (TABLE*) tables->table;
3327 	Field**			fields;
3328 	CHARSET_INFO*		index_charset;
3329 	const ib_rbt_node_t*	rbt_node;
3330 	fts_string_t		conv_str;
3331 	uint			dummy_errors;
3332 	char*			word_str;
3333 
3334 	DBUG_ENTER("i_s_fts_index_cache_fill_one_index");
3335 
3336 	fields = table->field;
3337 
3338 	index_charset = index_cache->charset;
3339 	conv_str.f_len = system_charset_info->mbmaxlen
3340 		* FTS_MAX_WORD_LEN_IN_CHAR;
3341 	conv_str.f_str = static_cast<byte*>(ut_malloc(conv_str.f_len));
3342 	conv_str.f_n_char = 0;
3343 
3344 	/* Go through each word in the index cache */
3345 	for (rbt_node = rbt_first(index_cache->words);
3346 	     rbt_node;
3347 	     rbt_node = rbt_next(index_cache->words, rbt_node)) {
3348 		fts_tokenizer_word_t* word;
3349 
3350 		word = rbt_value(fts_tokenizer_word_t, rbt_node);
3351 
3352 		/* Convert word from index charset to system_charset_info */
3353 		if (index_charset->cset != system_charset_info->cset) {
3354 			conv_str.f_n_char = my_convert(
3355 				reinterpret_cast<char*>(conv_str.f_str),
3356 				static_cast<uint32>(conv_str.f_len),
3357 				system_charset_info,
3358 				reinterpret_cast<char*>(word->text.f_str),
3359 				static_cast<uint32>(word->text.f_len),
3360 				index_charset, &dummy_errors);
3361 			ut_ad(conv_str.f_n_char <= conv_str.f_len);
3362 			conv_str.f_str[conv_str.f_n_char] = 0;
3363 			word_str = reinterpret_cast<char*>(conv_str.f_str);
3364 		} else {
3365 			word_str = reinterpret_cast<char*>(word->text.f_str);
3366 		}
3367 
3368 		/* Decrypt the ilist, and display Dod ID and word position */
3369 		for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
3370 			fts_node_t*	node;
3371 			byte*		ptr;
3372 			ulint		decoded = 0;
3373 			doc_id_t	doc_id = 0;
3374 
3375 			node = static_cast<fts_node_t*> (ib_vector_get(
3376 				word->nodes, i));
3377 
3378 			ptr = node->ilist;
3379 
3380 			while (decoded < node->ilist_size) {
3381 				ulint	pos = fts_decode_vlc(&ptr);
3382 
3383 				doc_id += pos;
3384 
3385 				/* Get position info */
3386 				while (*ptr) {
3387 					pos = fts_decode_vlc(&ptr);
3388 
3389 					OK(field_store_string(
3390 						fields[I_S_FTS_WORD],
3391 						word_str));
3392 
3393 					OK(fields[I_S_FTS_FIRST_DOC_ID]->store(
3394 						(longlong) node->first_doc_id,
3395 						true));
3396 
3397 					OK(fields[I_S_FTS_LAST_DOC_ID]->store(
3398 						(longlong) node->last_doc_id,
3399 						true));
3400 
3401 					OK(fields[I_S_FTS_DOC_COUNT]->store(
3402 						static_cast<double>(node->doc_count)));
3403 
3404 					OK(fields[I_S_FTS_ILIST_DOC_ID]->store(
3405 						(longlong) doc_id, true));
3406 
3407 					OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
3408 						static_cast<double>(pos)));
3409 
3410 					OK(schema_table_store_record(
3411 						thd, table));
3412 				}
3413 
3414 				++ptr;
3415 
3416 				decoded = ptr - (byte*) node->ilist;
3417 			}
3418 		}
3419 	}
3420 
3421 	ut_free(conv_str.f_str);
3422 
3423 	DBUG_RETURN(0);
3424 }
3425 /*******************************************************************//**
3426 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHED
3427 @return	0 on success, 1 on failure */
3428 static
3429 int
i_s_fts_index_cache_fill(THD * thd,TABLE_LIST * tables,Item *)3430 i_s_fts_index_cache_fill(
3431 /*=====================*/
3432 	THD*		thd,	/*!< in: thread */
3433 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
3434 	Item*		)	/*!< in: condition (ignored) */
3435 {
3436 	dict_table_t*		user_table;
3437 	fts_cache_t*		cache;
3438 
3439 	DBUG_ENTER("i_s_fts_index_cache_fill");
3440 
3441 	/* deny access to non-superusers */
3442 	if (check_global_access(thd, PROCESS_ACL)) {
3443 		DBUG_RETURN(0);
3444 	}
3445 
3446 	mysql_mutex_lock(&LOCK_global_system_variables);
3447 
3448         if (!fts_internal_tbl_name) {
3449                 mysql_mutex_unlock(&LOCK_global_system_variables);
3450                 DBUG_RETURN(0);
3451         }
3452 
3453 	std::string fts_table_name(fts_internal_tbl_name);
3454 	mysql_mutex_unlock(&LOCK_global_system_variables);
3455 
3456         if(!fts_table_name.c_str()) {
3457                 DBUG_RETURN(0);
3458         }
3459 
3460 	user_table = dict_table_open_on_name(
3461 		fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3462 
3463 	if (!user_table) {
3464 		DBUG_RETURN(0);
3465 	}
3466 
3467 	if (user_table->fts == NULL || user_table->fts->cache == NULL) {
3468 		dict_table_close(user_table, FALSE, FALSE);
3469 
3470 		DBUG_RETURN(0);
3471 	}
3472 
3473 	cache = user_table->fts->cache;
3474 
3475 	ut_a(cache);
3476 
3477 	/* Check if cache is being synced.
3478 	Note: we wait till cache is being synced. */
3479 	while (cache->sync->in_progress) {
3480 		os_event_wait(cache->sync->event);
3481 	}
3482 	for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) {
3483 		fts_index_cache_t*      index_cache;
3484 
3485 		index_cache = static_cast<fts_index_cache_t*> (
3486 			ib_vector_get(cache->indexes, i));
3487 
3488 		i_s_fts_index_cache_fill_one_index(index_cache, thd, tables);
3489 	}
3490 
3491 	dict_table_close(user_table, FALSE, FALSE);
3492 
3493 	DBUG_RETURN(0);
3494 }
3495 
3496 /*******************************************************************//**
3497 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
3498 @return	0 on success */
3499 static
3500 int
i_s_fts_index_cache_init(void * p)3501 i_s_fts_index_cache_init(
3502 /*=====================*/
3503 	void*	p)	/*!< in/out: table schema object */
3504 {
3505 	DBUG_ENTER("i_s_fts_index_cache_init");
3506 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3507 
3508 	schema->fields_info = i_s_fts_index_fields_info;
3509 	schema->fill_table = i_s_fts_index_cache_fill;
3510 
3511 	DBUG_RETURN(0);
3512 }
3513 
3514 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_ft_index_cache =
3515 {
3516 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3517 	/* int */
3518 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3519 
3520 	/* pointer to type-specific plugin descriptor */
3521 	/* void* */
3522 	STRUCT_FLD(info, &i_s_info),
3523 
3524 	/* plugin name */
3525 	/* const char* */
3526 	STRUCT_FLD(name, "INNODB_FT_INDEX_CACHE"),
3527 
3528 	/* plugin author (for SHOW PLUGINS) */
3529 	/* const char* */
3530 	STRUCT_FLD(author, plugin_author),
3531 
3532 	/* general descriptive text (for SHOW PLUGINS) */
3533 	/* const char* */
3534 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX CACHED"),
3535 
3536 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3537 	/* int */
3538 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3539 
3540 	/* the function to invoke when plugin is loaded */
3541 	/* int (*)(void*); */
3542 	STRUCT_FLD(init, i_s_fts_index_cache_init),
3543 
3544 	/* the function to invoke when plugin is unloaded */
3545 	/* int (*)(void*); */
3546 	STRUCT_FLD(deinit, i_s_common_deinit),
3547 
3548 	/* plugin version (for SHOW PLUGINS) */
3549 	/* unsigned int */
3550 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
3551 
3552 	/* struct st_mysql_show_var* */
3553 	STRUCT_FLD(status_vars, NULL),
3554 
3555 	/* struct st_mysql_sys_var** */
3556 	STRUCT_FLD(system_vars, NULL),
3557 
3558 	/* reserved for dependency checking */
3559 	/* void* */
3560 	STRUCT_FLD(__reserved1, NULL),
3561 
3562 	/* Plugin flags */
3563 	/* unsigned long */
3564 	STRUCT_FLD(flags, 0UL),
3565 };
3566 
3567 /*******************************************************************//**
3568 Go through a FTS index auxiliary table, fetch its rows and fill
3569 FTS word cache structure.
3570 @return	DB_SUCCESS on success, otherwise error code */
3571 static
3572 dberr_t
i_s_fts_index_table_fill_selected(dict_index_t * index,ib_vector_t * words,ulint selected,fts_string_t * word)3573 i_s_fts_index_table_fill_selected(
3574 /*==============================*/
3575 	dict_index_t*		index,		/*!< in: FTS index */
3576 	ib_vector_t*		words,		/*!< in/out: vector to hold
3577 						fetched words */
3578 	ulint			selected,	/*!< in: selected FTS index */
3579 	fts_string_t*		word)		/*!< in: word to select */
3580 {
3581 	pars_info_t*		info;
3582 	fts_table_t		fts_table;
3583 	trx_t*			trx;
3584 	que_t*			graph;
3585 	dberr_t			error;
3586 	fts_fetch_t		fetch;
3587 
3588 	info = pars_info_create();
3589 
3590 	fetch.read_arg = words;
3591 	fetch.read_record = fts_optimize_index_fetch_node;
3592 	fetch.total_memory = 0;
3593 
3594 	DBUG_EXECUTE_IF("fts_instrument_result_cache_limit",
3595 	        fts_result_cache_limit = 8192;
3596 	);
3597 
3598 	trx = trx_allocate_for_background();
3599 
3600 	trx->op_info = "fetching FTS index nodes";
3601 
3602 	pars_info_bind_function(info, "my_func", fetch.read_record, &fetch);
3603 	pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
3604 
3605 	FTS_INIT_INDEX_TABLE(&fts_table, fts_get_suffix(selected),
3606 			     FTS_INDEX_TABLE, index);
3607 
3608 	graph = fts_parse_sql(
3609 		&fts_table, info,
3610 		"DECLARE FUNCTION my_func;\n"
3611 		"DECLARE CURSOR c IS"
3612 		" SELECT word, doc_count, first_doc_id, last_doc_id, "
3613 		"ilist\n"
3614 		" FROM %s WHERE word >= :word;\n"
3615 		"BEGIN\n"
3616 		"\n"
3617 		"OPEN c;\n"
3618 		"WHILE 1 = 1 LOOP\n"
3619 		"  FETCH c INTO my_func();\n"
3620 		"  IF c % NOTFOUND THEN\n"
3621 		"    EXIT;\n"
3622 		"  END IF;\n"
3623 		"END LOOP;\n"
3624 		"CLOSE c;");
3625 
3626 	for(;;) {
3627 		error = fts_eval_sql(trx, graph);
3628 
3629 		if (error == DB_SUCCESS) {
3630 			fts_sql_commit(trx);
3631 
3632 			break;
3633 		} else {
3634 			fts_sql_rollback(trx);
3635 
3636 			ut_print_timestamp(stderr);
3637 
3638 			if (error == DB_LOCK_WAIT_TIMEOUT) {
3639 				fprintf(stderr, "  InnoDB: Warning: "
3640 					"lock wait timeout reading "
3641 					"FTS index.  Retrying!\n");
3642 
3643 				trx->error_state = DB_SUCCESS;
3644 			} else {
3645 				fprintf(stderr, "  InnoDB: Error: %d "
3646 				"while reading FTS index.\n", error);
3647 				break;
3648 			}
3649 		}
3650 	}
3651 
3652 	mutex_enter(&dict_sys->mutex);
3653 	que_graph_free(graph);
3654 	mutex_exit(&dict_sys->mutex);
3655 
3656 	trx_free_for_background(trx);
3657 
3658 	if (fetch.total_memory >= fts_result_cache_limit) {
3659 		error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
3660 	}
3661 
3662 	return(error);
3663 }
3664 
3665 /*******************************************************************//**
3666 Free words. */
3667 static
3668 void
i_s_fts_index_table_free_one_fetch(ib_vector_t * words)3669 i_s_fts_index_table_free_one_fetch(
3670 /*===============================*/
3671 	ib_vector_t*		words)		/*!< in: words fetched */
3672 {
3673 	for (ulint i = 0; i < ib_vector_size(words); i++) {
3674 		fts_word_t*	word;
3675 
3676 		word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3677 
3678 		for (ulint j = 0; j < ib_vector_size(word->nodes); j++) {
3679 			fts_node_t*     node;
3680 
3681 			node = static_cast<fts_node_t*> (ib_vector_get(
3682 				word->nodes, j));
3683 			ut_free(node->ilist);
3684 		}
3685 
3686 		fts_word_free(word);
3687 	}
3688 
3689 	ib_vector_reset(words);
3690 }
3691 
3692 /*******************************************************************//**
3693 Go through words, fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3694 @return	0 on success, 1 on failure */
3695 static
3696 int
i_s_fts_index_table_fill_one_fetch(CHARSET_INFO * index_charset,THD * thd,TABLE_LIST * tables,ib_vector_t * words,fts_string_t * conv_str,bool has_more)3697 i_s_fts_index_table_fill_one_fetch(
3698 /*===============================*/
3699 	CHARSET_INFO*		index_charset,	/*!< in: FTS index charset */
3700 	THD*			thd,		/*!< in: thread */
3701 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
3702 	ib_vector_t*		words,		/*!< in: words fetched */
3703 	fts_string_t*		conv_str,	/*!< in: string for conversion*/
3704 	bool			has_more)	/*!< in: has more to fetch */
3705 {
3706 	TABLE*			table = (TABLE*) tables->table;
3707 	Field**			fields;
3708 	uint			dummy_errors;
3709 	char*			word_str;
3710 	ulint			words_size;
3711 	int			ret = 0;
3712 
3713 	DBUG_ENTER("i_s_fts_index_table_fill_one_fetch");
3714 
3715 	fields = table->field;
3716 
3717 	words_size = ib_vector_size(words);
3718 	if (has_more) {
3719 		/* the last word is not fetched completely. */
3720 		ut_ad(words_size > 1);
3721 		words_size -= 1;
3722 	}
3723 
3724 	/* Go through each word in the index cache */
3725 	for (ulint i = 0; i < words_size; i++) {
3726 		fts_word_t*	word;
3727 
3728 		word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3729 
3730 		word->text.f_str[word->text.f_len] = 0;
3731 
3732 		/* Convert word from index charset to system_charset_info */
3733 		if (index_charset->cset != system_charset_info->cset) {
3734 			conv_str->f_n_char = my_convert(
3735 				reinterpret_cast<char*>(conv_str->f_str),
3736 				static_cast<uint32>(conv_str->f_len),
3737 				system_charset_info,
3738 				reinterpret_cast<char*>(word->text.f_str),
3739 				static_cast<uint32>(word->text.f_len),
3740 				index_charset, &dummy_errors);
3741 			ut_ad(conv_str->f_n_char <= conv_str->f_len);
3742 			conv_str->f_str[conv_str->f_n_char] = 0;
3743 			word_str = reinterpret_cast<char*>(conv_str->f_str);
3744 		} else {
3745 			word_str = reinterpret_cast<char*>(word->text.f_str);
3746 		}
3747 
3748 		/* Decrypt the ilist, and display Dod ID and word position */
3749 		for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
3750 			fts_node_t*	node;
3751 			byte*		ptr;
3752 			ulint		decoded = 0;
3753 			doc_id_t	doc_id = 0;
3754 
3755 			node = static_cast<fts_node_t*> (ib_vector_get(
3756 				word->nodes, i));
3757 
3758 			ptr = node->ilist;
3759 
3760 			while (decoded < node->ilist_size) {
3761 				ulint	pos = fts_decode_vlc(&ptr);
3762 
3763 				doc_id += pos;
3764 
3765 				/* Get position info */
3766 				while (*ptr) {
3767 					pos = fts_decode_vlc(&ptr);
3768 
3769 					OK(field_store_string(
3770 						fields[I_S_FTS_WORD],
3771 						word_str));
3772 
3773 					OK(fields[I_S_FTS_FIRST_DOC_ID]->store(
3774 						(longlong) node->first_doc_id,
3775 						true));
3776 
3777 					OK(fields[I_S_FTS_LAST_DOC_ID]->store(
3778 						(longlong) node->last_doc_id,
3779 						true));
3780 
3781 					OK(fields[I_S_FTS_DOC_COUNT]->store(
3782 						static_cast<double>(node->doc_count)));
3783 
3784 					OK(fields[I_S_FTS_ILIST_DOC_ID]->store(
3785 						(longlong) doc_id, true));
3786 
3787 					OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
3788 						static_cast<double>(pos)));
3789 
3790 					OK(schema_table_store_record(
3791 						thd, table));
3792 				}
3793 
3794 				++ptr;
3795 
3796 				decoded = ptr - (byte*) node->ilist;
3797 			}
3798 		}
3799 	}
3800 
3801 	i_s_fts_index_table_free_one_fetch(words);
3802 
3803 	DBUG_RETURN(ret);
3804 }
3805 
3806 /*******************************************************************//**
3807 Go through a FTS index and its auxiliary tables, fetch rows in each table
3808 and fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3809 @return	0 on success, 1 on failure */
3810 static
3811 int
i_s_fts_index_table_fill_one_index(dict_index_t * index,THD * thd,TABLE_LIST * tables)3812 i_s_fts_index_table_fill_one_index(
3813 /*===============================*/
3814 	dict_index_t*		index,		/*!< in: FTS index */
3815 	THD*			thd,		/*!< in: thread */
3816 	TABLE_LIST*		tables)		/*!< in/out: tables to fill */
3817 {
3818 	ib_vector_t*		words;
3819 	mem_heap_t*		heap;
3820 	fts_string_t		word;
3821 	CHARSET_INFO*		index_charset;
3822 	fts_string_t		conv_str;
3823 	dberr_t			error;
3824 	int			ret = 0;
3825 
3826 	DBUG_ENTER("i_s_fts_index_table_fill_one_index");
3827 	DBUG_ASSERT(!dict_index_is_online_ddl(index));
3828 
3829 	heap = mem_heap_create(1024);
3830 
3831 	words = ib_vector_create(ib_heap_allocator_create(heap),
3832 				 sizeof(fts_word_t), 256);
3833 
3834 	word.f_str = NULL;
3835 	word.f_len = 0;
3836 	word.f_n_char = 0;
3837 
3838 	index_charset = fts_index_get_charset(index);
3839 	conv_str.f_len = system_charset_info->mbmaxlen
3840 		* FTS_MAX_WORD_LEN_IN_CHAR;
3841 	conv_str.f_str = static_cast<byte*>(ut_malloc(conv_str.f_len));
3842 	conv_str.f_n_char = 0;
3843 
3844 	/* Iterate through each auxiliary table as described in
3845 	fts_index_selector */
3846 	for (ulint selected = 0; fts_index_selector[selected].value;
3847 	     selected++) {
3848 		bool	has_more = false;
3849 
3850 		do {
3851 			/* Fetch from index */
3852 			error = i_s_fts_index_table_fill_selected(
3853 				index, words, selected, &word);
3854 
3855 			if (error == DB_SUCCESS) {
3856 				has_more = false;
3857 			} else if (error == DB_FTS_EXCEED_RESULT_CACHE_LIMIT) {
3858 				has_more = true;
3859 			} else {
3860 				i_s_fts_index_table_free_one_fetch(words);
3861 				ret = 1;
3862 				goto func_exit;
3863 			}
3864 
3865 			if (has_more) {
3866 				fts_word_t*	last_word;
3867 
3868 				/* Prepare start point for next fetch */
3869 				last_word = static_cast<fts_word_t*>(ib_vector_last(words));
3870 				ut_ad(last_word != NULL);
3871 				fts_utf8_string_dup(&word, &last_word->text, heap);
3872 			}
3873 
3874 			/* Fill into tables */
3875 			ret = i_s_fts_index_table_fill_one_fetch(
3876 				index_charset, thd, tables, words, &conv_str, has_more);
3877 
3878 			if (ret != 0) {
3879 				i_s_fts_index_table_free_one_fetch(words);
3880 				goto func_exit;
3881 			}
3882 		} while (has_more);
3883 	}
3884 
3885 func_exit:
3886 	ut_free(conv_str.f_str);
3887 	mem_heap_free(heap);
3888 
3889 	DBUG_RETURN(ret);
3890 }
3891 /*******************************************************************//**
3892 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3893 @return	0 on success, 1 on failure */
3894 static
3895 int
i_s_fts_index_table_fill(THD * thd,TABLE_LIST * tables,Item *)3896 i_s_fts_index_table_fill(
3897 /*=====================*/
3898 	THD*		thd,	/*!< in: thread */
3899 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
3900 	Item*		)	/*!< in: condition (ignored) */
3901 {
3902 	dict_table_t*		user_table;
3903 	dict_index_t*		index;
3904 
3905 	DBUG_ENTER("i_s_fts_index_table_fill");
3906 
3907 	/* deny access to non-superusers */
3908 	if (check_global_access(thd, PROCESS_ACL)) {
3909 		DBUG_RETURN(0);
3910 	}
3911 
3912 	mysql_mutex_lock(&LOCK_global_system_variables);
3913 
3914         if (!fts_internal_tbl_name) {
3915                 mysql_mutex_unlock(&LOCK_global_system_variables);
3916                 DBUG_RETURN(0);
3917         }
3918 
3919 	std::string fts_table_name(fts_internal_tbl_name);
3920 	mysql_mutex_unlock(&LOCK_global_system_variables);
3921 
3922         if(!fts_table_name.c_str()) {
3923                 DBUG_RETURN(0);
3924         }
3925 
3926 	/* Prevent DDL to drop fts aux tables. */
3927 	rw_lock_s_lock(&dict_operation_lock);
3928 
3929 	user_table = dict_table_open_on_name(
3930 		fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3931 
3932 	if (!user_table) {
3933 		rw_lock_s_unlock(&dict_operation_lock);
3934 
3935 		DBUG_RETURN(0);
3936 	}
3937 
3938 	for (index = dict_table_get_first_index(user_table);
3939 	     index; index = dict_table_get_next_index(index)) {
3940 		if (index->type & DICT_FTS) {
3941 			i_s_fts_index_table_fill_one_index(index, thd, tables);
3942 		}
3943 	}
3944 
3945 	dict_table_close(user_table, FALSE, FALSE);
3946 
3947 	rw_lock_s_unlock(&dict_operation_lock);
3948 
3949 	DBUG_RETURN(0);
3950 }
3951 
3952 /*******************************************************************//**
3953 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3954 @return	0 on success */
3955 static
3956 int
i_s_fts_index_table_init(void * p)3957 i_s_fts_index_table_init(
3958 /*=====================*/
3959 	void*	p)	/*!< in/out: table schema object */
3960 {
3961 	DBUG_ENTER("i_s_fts_index_table_init");
3962 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3963 
3964 	schema->fields_info = i_s_fts_index_fields_info;
3965 	schema->fill_table = i_s_fts_index_table_fill;
3966 
3967 	DBUG_RETURN(0);
3968 }
3969 
3970 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_ft_index_table =
3971 {
3972 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3973 	/* int */
3974 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3975 
3976 	/* pointer to type-specific plugin descriptor */
3977 	/* void* */
3978 	STRUCT_FLD(info, &i_s_info),
3979 
3980 	/* plugin name */
3981 	/* const char* */
3982 	STRUCT_FLD(name, "INNODB_FT_INDEX_TABLE"),
3983 
3984 	/* plugin author (for SHOW PLUGINS) */
3985 	/* const char* */
3986 	STRUCT_FLD(author, plugin_author),
3987 
3988 	/* general descriptive text (for SHOW PLUGINS) */
3989 	/* const char* */
3990 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX TABLE"),
3991 
3992 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3993 	/* int */
3994 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3995 
3996 	/* the function to invoke when plugin is loaded */
3997 	/* int (*)(void*); */
3998 	STRUCT_FLD(init, i_s_fts_index_table_init),
3999 
4000 	/* the function to invoke when plugin is unloaded */
4001 	/* int (*)(void*); */
4002 	STRUCT_FLD(deinit, i_s_common_deinit),
4003 
4004 	/* plugin version (for SHOW PLUGINS) */
4005 	/* unsigned int */
4006 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
4007 
4008 	/* struct st_mysql_show_var* */
4009 	STRUCT_FLD(status_vars, NULL),
4010 
4011 	/* struct st_mysql_sys_var** */
4012 	STRUCT_FLD(system_vars, NULL),
4013 
4014 	/* reserved for dependency checking */
4015 	/* void* */
4016 	STRUCT_FLD(__reserved1, NULL),
4017 
4018 	/* Plugin flags */
4019 	/* unsigned long */
4020 	STRUCT_FLD(flags, 0UL),
4021 };
4022 
4023 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG */
4024 static ST_FIELD_INFO	i_s_fts_config_fields_info[] =
4025 {
4026 #define	FTS_CONFIG_KEY			0
4027 	{STRUCT_FLD(field_name,		"KEY"),
4028 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
4029 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4030 	 STRUCT_FLD(value,		0),
4031 	 STRUCT_FLD(field_flags,	0),
4032 	 STRUCT_FLD(old_name,		""),
4033 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4034 
4035 #define	FTS_CONFIG_VALUE		1
4036 	{STRUCT_FLD(field_name,		"VALUE"),
4037 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
4038 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4039 	 STRUCT_FLD(value,		0),
4040 	 STRUCT_FLD(field_flags,	0),
4041 	 STRUCT_FLD(old_name,		""),
4042 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4043 
4044 	END_OF_ST_FIELD_INFO
4045 };
4046 
4047 static const char* fts_config_key[] = {
4048 	FTS_OPTIMIZE_LIMIT_IN_SECS,
4049 	FTS_SYNCED_DOC_ID,
4050 	FTS_STOPWORD_TABLE_NAME,
4051 	FTS_USE_STOPWORD,
4052         NULL
4053 };
4054 
4055 /*******************************************************************//**
4056 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4057 @return	0 on success, 1 on failure */
4058 static
4059 int
i_s_fts_config_fill(THD * thd,TABLE_LIST * tables,Item *)4060 i_s_fts_config_fill(
4061 /*================*/
4062 	THD*		thd,		/*!< in: thread */
4063 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
4064 	Item*		)	/*!< in: condition (ignored) */
4065 {
4066 	Field**			fields;
4067 	TABLE*			table = (TABLE*) tables->table;
4068 	trx_t*			trx;
4069 	fts_table_t		fts_table;
4070 	dict_table_t*		user_table;
4071 	ulint			i = 0;
4072 	dict_index_t*		index = NULL;
4073 	unsigned char		str[FTS_MAX_CONFIG_VALUE_LEN + 1];
4074 
4075 	DBUG_ENTER("i_s_fts_config_fill");
4076 
4077 	/* deny access to non-superusers */
4078 	if (check_global_access(thd, PROCESS_ACL)) {
4079 		DBUG_RETURN(0);
4080 	}
4081 
4082 	mysql_mutex_lock(&LOCK_global_system_variables);
4083 
4084         if (!fts_internal_tbl_name) {
4085                 mysql_mutex_unlock(&LOCK_global_system_variables);
4086                 DBUG_RETURN(0);
4087         }
4088 
4089 	std::string fts_table_name(fts_internal_tbl_name);
4090 	mysql_mutex_unlock(&LOCK_global_system_variables);
4091 
4092         if(!fts_table_name.c_str()) {
4093                 DBUG_RETURN(0);
4094         }
4095 
4096 	DEBUG_SYNC_C("i_s_fts_config_fille_check");
4097 
4098 	fields = table->field;
4099 
4100 	/* Prevent DDL to drop fts aux tables. */
4101 	rw_lock_s_lock(&dict_operation_lock);
4102 
4103 	user_table = dict_table_open_on_name(
4104 		fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
4105 
4106 	if (!user_table) {
4107 		rw_lock_s_unlock(&dict_operation_lock);
4108 
4109 		DBUG_RETURN(0);
4110 	} else if (!dict_table_has_fts_index(user_table)) {
4111 		dict_table_close(user_table, FALSE, FALSE);
4112 
4113 		rw_lock_s_unlock(&dict_operation_lock);
4114 
4115 		DBUG_RETURN(0);
4116 	}
4117 
4118 	trx = trx_allocate_for_background();
4119 	trx->op_info = "Select for FTS CONFIG TABLE";
4120 
4121 	FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE, user_table);
4122 
4123 	if (!ib_vector_is_empty(user_table->fts->indexes)) {
4124 		index = (dict_index_t*) ib_vector_getp_const(
4125 				user_table->fts->indexes, 0);
4126 		DBUG_ASSERT(!dict_index_is_online_ddl(index));
4127 	}
4128 
4129 	while (fts_config_key[i]) {
4130 		fts_string_t	value;
4131 		char*		key_name;
4132 		ulint		allocated = FALSE;
4133 
4134 		value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
4135 
4136 		value.f_str = str;
4137 
4138 		if (index
4139 		    && strcmp(fts_config_key[i], FTS_TOTAL_WORD_COUNT) == 0) {
4140 			key_name = fts_config_create_index_param_name(
4141 				fts_config_key[i], index);
4142 			allocated = TRUE;
4143 		} else {
4144 			key_name = (char*) fts_config_key[i];
4145 		}
4146 
4147 		fts_config_get_value(trx, &fts_table, key_name, &value);
4148 
4149 		if (allocated) {
4150 			ut_free(key_name);
4151 		}
4152 
4153 		OK(field_store_string(
4154                         fields[FTS_CONFIG_KEY], fts_config_key[i]));
4155 
4156 		OK(field_store_string(
4157                         fields[FTS_CONFIG_VALUE], (const char*) value.f_str));
4158 
4159 		OK(schema_table_store_record(thd, table));
4160 
4161 		i++;
4162 	}
4163 
4164 	fts_sql_commit(trx);
4165 
4166 	trx_free_for_background(trx);
4167 
4168 	dict_table_close(user_table, FALSE, FALSE);
4169 
4170 	rw_lock_s_unlock(&dict_operation_lock);
4171 
4172 	DBUG_RETURN(0);
4173 }
4174 
4175 /*******************************************************************//**
4176 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4177 @return	0 on success */
4178 static
4179 int
i_s_fts_config_init(void * p)4180 i_s_fts_config_init(
4181 /*=================*/
4182 	void*	p)	/*!< in/out: table schema object */
4183 {
4184 	DBUG_ENTER("i_s_fts_config_init");
4185 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
4186 
4187 	schema->fields_info = i_s_fts_config_fields_info;
4188 	schema->fill_table = i_s_fts_config_fill;
4189 
4190 	DBUG_RETURN(0);
4191 }
4192 
4193 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_ft_config =
4194 {
4195 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
4196 	/* int */
4197 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4198 
4199 	/* pointer to type-specific plugin descriptor */
4200 	/* void* */
4201 	STRUCT_FLD(info, &i_s_info),
4202 
4203 	/* plugin name */
4204 	/* const char* */
4205 	STRUCT_FLD(name, "INNODB_FT_CONFIG"),
4206 
4207 	/* plugin author (for SHOW PLUGINS) */
4208 	/* const char* */
4209 	STRUCT_FLD(author, plugin_author),
4210 
4211 	/* general descriptive text (for SHOW PLUGINS) */
4212 	/* const char* */
4213 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS CONFIG TABLE"),
4214 
4215 	/* the plugin license (PLUGIN_LICENSE_XXX) */
4216 	/* int */
4217 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4218 
4219 	/* the function to invoke when plugin is loaded */
4220 	/* int (*)(void*); */
4221 	STRUCT_FLD(init, i_s_fts_config_init),
4222 
4223 	/* the function to invoke when plugin is unloaded */
4224 	/* int (*)(void*); */
4225 	STRUCT_FLD(deinit, i_s_common_deinit),
4226 
4227 	/* plugin version (for SHOW PLUGINS) */
4228 	/* unsigned int */
4229 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
4230 
4231 	/* struct st_mysql_show_var* */
4232 	STRUCT_FLD(status_vars, NULL),
4233 
4234 	/* struct st_mysql_sys_var** */
4235 	STRUCT_FLD(system_vars, NULL),
4236 
4237 	/* reserved for dependency checking */
4238 	/* void* */
4239 	STRUCT_FLD(__reserved1, NULL),
4240 
4241 	/* Plugin flags */
4242 	/* unsigned long */
4243 	STRUCT_FLD(flags, 0UL),
4244 };
4245 
4246 /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
4247 static ST_FIELD_INFO	i_s_innodb_buffer_stats_fields_info[] =
4248 {
4249 #define IDX_BUF_STATS_POOL_ID		0
4250 	{STRUCT_FLD(field_name,		"POOL_ID"),
4251 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4252 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4253 	 STRUCT_FLD(value,		0),
4254 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4255 	 STRUCT_FLD(old_name,		""),
4256 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4257 
4258 #define IDX_BUF_STATS_POOL_SIZE		1
4259 	{STRUCT_FLD(field_name,		"POOL_SIZE"),
4260 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4261 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4262 	 STRUCT_FLD(value,		0),
4263 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4264 	 STRUCT_FLD(old_name,		""),
4265 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4266 
4267 #define IDX_BUF_STATS_FREE_BUFFERS	2
4268 	{STRUCT_FLD(field_name,		"FREE_BUFFERS"),
4269 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4270 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4271 	 STRUCT_FLD(value,		0),
4272 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4273 	 STRUCT_FLD(old_name,		""),
4274 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4275 
4276 #define IDX_BUF_STATS_LRU_LEN		3
4277 	{STRUCT_FLD(field_name,		"DATABASE_PAGES"),
4278 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4279 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4280 	 STRUCT_FLD(value,		0),
4281 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4282 	 STRUCT_FLD(old_name,		""),
4283 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4284 
4285 #define IDX_BUF_STATS_OLD_LRU_LEN	4
4286 	{STRUCT_FLD(field_name,		"OLD_DATABASE_PAGES"),
4287 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4288 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4289 	 STRUCT_FLD(value,		0),
4290 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4291 	 STRUCT_FLD(old_name,		""),
4292 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4293 
4294 #define IDX_BUF_STATS_FLUSH_LIST_LEN	5
4295 	{STRUCT_FLD(field_name,		"MODIFIED_DATABASE_PAGES"),
4296 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4297 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4298 	 STRUCT_FLD(value,		0),
4299 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4300 	 STRUCT_FLD(old_name,		""),
4301 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4302 
4303 #define IDX_BUF_STATS_PENDING_ZIP	6
4304 	{STRUCT_FLD(field_name,		"PENDING_DECOMPRESS"),
4305 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4306 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4307 	 STRUCT_FLD(value,		0),
4308 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4309 	 STRUCT_FLD(old_name,		""),
4310 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4311 
4312 #define IDX_BUF_STATS_PENDING_READ	7
4313 	{STRUCT_FLD(field_name,		"PENDING_READS"),
4314 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4315 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4316 	 STRUCT_FLD(value,		0),
4317 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4318 	 STRUCT_FLD(old_name,		""),
4319 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4320 
4321 #define IDX_BUF_STATS_FLUSH_LRU		8
4322 	{STRUCT_FLD(field_name,		"PENDING_FLUSH_LRU"),
4323 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4324 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4325 	 STRUCT_FLD(value,		0),
4326 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4327 	 STRUCT_FLD(old_name,		""),
4328 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4329 
4330 #define IDX_BUF_STATS_FLUSH_LIST	9
4331 	{STRUCT_FLD(field_name,		"PENDING_FLUSH_LIST"),
4332 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4333 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4334 	 STRUCT_FLD(value,		0),
4335 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4336 	 STRUCT_FLD(old_name,		""),
4337 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4338 
4339 #define IDX_BUF_STATS_PAGE_YOUNG	10
4340 	{STRUCT_FLD(field_name,		"PAGES_MADE_YOUNG"),
4341 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4342 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4343 	 STRUCT_FLD(value,		0),
4344 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4345 	 STRUCT_FLD(old_name,		""),
4346 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4347 
4348 #define IDX_BUF_STATS_PAGE_NOT_YOUNG	11
4349 	{STRUCT_FLD(field_name,		"PAGES_NOT_MADE_YOUNG"),
4350 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4351 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4352 	 STRUCT_FLD(value,		0),
4353 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4354 	 STRUCT_FLD(old_name,		""),
4355 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4356 
4357 #define	IDX_BUF_STATS_PAGE_YOUNG_RATE	12
4358 	{STRUCT_FLD(field_name,		"PAGES_MADE_YOUNG_RATE"),
4359 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4360 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4361 	 STRUCT_FLD(value,		0),
4362 	 STRUCT_FLD(field_flags,	0),
4363 	 STRUCT_FLD(old_name,		""),
4364 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4365 
4366 #define	IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
4367 	{STRUCT_FLD(field_name,		"PAGES_MADE_NOT_YOUNG_RATE"),
4368 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4369 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4370 	 STRUCT_FLD(value,		0),
4371 	 STRUCT_FLD(field_flags,	0),
4372 	 STRUCT_FLD(old_name,		""),
4373 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4374 
4375 #define IDX_BUF_STATS_PAGE_READ		14
4376 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_READ"),
4377 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4378 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4379 	 STRUCT_FLD(value,		0),
4380 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4381 	 STRUCT_FLD(old_name,		""),
4382 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4383 
4384 #define IDX_BUF_STATS_PAGE_CREATED	15
4385 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_CREATED"),
4386 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4387 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4388 	 STRUCT_FLD(value,		0),
4389 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4390 	 STRUCT_FLD(old_name,		""),
4391 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4392 
4393 #define IDX_BUF_STATS_PAGE_WRITTEN	16
4394 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_WRITTEN"),
4395 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4396 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4397 	 STRUCT_FLD(value,		0),
4398 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4399 	 STRUCT_FLD(old_name,		""),
4400 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4401 
4402 #define	IDX_BUF_STATS_PAGE_READ_RATE	17
4403 	{STRUCT_FLD(field_name,		"PAGES_READ_RATE"),
4404 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4405 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4406 	 STRUCT_FLD(value,		0),
4407 	 STRUCT_FLD(field_flags,	0),
4408 	 STRUCT_FLD(old_name,		""),
4409 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4410 
4411 #define	IDX_BUF_STATS_PAGE_CREATE_RATE	18
4412 	{STRUCT_FLD(field_name,		"PAGES_CREATE_RATE"),
4413 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4414 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4415 	 STRUCT_FLD(value,		0),
4416 	 STRUCT_FLD(field_flags,	0),
4417 	 STRUCT_FLD(old_name,		""),
4418 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4419 
4420 #define	IDX_BUF_STATS_PAGE_WRITTEN_RATE	19
4421 	{STRUCT_FLD(field_name,		"PAGES_WRITTEN_RATE"),
4422 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4423 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4424 	 STRUCT_FLD(value,		0),
4425 	 STRUCT_FLD(field_flags,	0),
4426 	 STRUCT_FLD(old_name,		""),
4427 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4428 
4429 #define IDX_BUF_STATS_GET		20
4430 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_GET"),
4431 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4432 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4433 	 STRUCT_FLD(value,		0),
4434 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4435 	 STRUCT_FLD(old_name,		""),
4436 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4437 
4438 #define IDX_BUF_STATS_HIT_RATE		21
4439 	{STRUCT_FLD(field_name,		"HIT_RATE"),
4440 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4441 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4442 	 STRUCT_FLD(value,		0),
4443 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4444 	 STRUCT_FLD(old_name,		""),
4445 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4446 
4447 #define IDX_BUF_STATS_MADE_YOUNG_PCT	22
4448 	{STRUCT_FLD(field_name,		"YOUNG_MAKE_PER_THOUSAND_GETS"),
4449 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4450 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4451 	 STRUCT_FLD(value,		0),
4452 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4453 	 STRUCT_FLD(old_name,		""),
4454 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4455 
4456 #define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
4457 	{STRUCT_FLD(field_name,		"NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
4458 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4459 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4460 	 STRUCT_FLD(value,		0),
4461 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4462 	 STRUCT_FLD(old_name,		""),
4463 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4464 
4465 #define IDX_BUF_STATS_READ_AHREAD	24
4466 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_READ_AHEAD"),
4467 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4468 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4469 	 STRUCT_FLD(value,		0),
4470 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4471 	 STRUCT_FLD(old_name,		""),
4472 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4473 
4474 #define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
4475 	{STRUCT_FLD(field_name,		"NUMBER_READ_AHEAD_EVICTED"),
4476 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4477 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4478 	 STRUCT_FLD(value,		0),
4479 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4480 	 STRUCT_FLD(old_name,		""),
4481 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4482 
4483 #define	IDX_BUF_STATS_READ_AHEAD_RATE	26
4484 	{STRUCT_FLD(field_name,		"READ_AHEAD_RATE"),
4485 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4486 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4487 	 STRUCT_FLD(value,		0),
4488 	 STRUCT_FLD(field_flags,	0),
4489 	 STRUCT_FLD(old_name,		""),
4490 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4491 
4492 #define	IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
4493 	{STRUCT_FLD(field_name,		"READ_AHEAD_EVICTED_RATE"),
4494 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4495 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4496 	 STRUCT_FLD(value,		0),
4497 	 STRUCT_FLD(field_flags,	0),
4498 	 STRUCT_FLD(old_name,		""),
4499 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4500 
4501 #define IDX_BUF_STATS_LRU_IO_SUM	28
4502 	{STRUCT_FLD(field_name,		"LRU_IO_TOTAL"),
4503 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4504 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4505 	 STRUCT_FLD(value,		0),
4506 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4507 	 STRUCT_FLD(old_name,		""),
4508 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4509 
4510 #define IDX_BUF_STATS_LRU_IO_CUR	29
4511 	{STRUCT_FLD(field_name,		"LRU_IO_CURRENT"),
4512 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4513 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4514 	 STRUCT_FLD(value,		0),
4515 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4516 	 STRUCT_FLD(old_name,		""),
4517 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4518 
4519 #define IDX_BUF_STATS_UNZIP_SUM		30
4520 	{STRUCT_FLD(field_name,		"UNCOMPRESS_TOTAL"),
4521 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4522 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4523 	 STRUCT_FLD(value,		0),
4524 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4525 	 STRUCT_FLD(old_name,		""),
4526 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4527 
4528 #define IDX_BUF_STATS_UNZIP_CUR		31
4529 	{STRUCT_FLD(field_name,		"UNCOMPRESS_CURRENT"),
4530 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4531 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4532 	 STRUCT_FLD(value,		0),
4533 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4534 	 STRUCT_FLD(old_name,		""),
4535 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4536 
4537 	END_OF_ST_FIELD_INFO
4538 };
4539 
4540 /*******************************************************************//**
4541 Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
4542 buffer pool
4543 @return	0 on success, 1 on failure */
4544 static
4545 int
i_s_innodb_stats_fill(THD * thd,TABLE_LIST * tables,const buf_pool_info_t * info)4546 i_s_innodb_stats_fill(
4547 /*==================*/
4548 	THD*			thd,		/*!< in: thread */
4549 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
4550 	const buf_pool_info_t*	info)		/*!< in: buffer pool
4551 						information */
4552 {
4553 	TABLE*			table;
4554 	Field**			fields;
4555 
4556 	DBUG_ENTER("i_s_innodb_stats_fill");
4557 
4558 	table = tables->table;
4559 
4560 	fields = table->field;
4561 
4562 	OK(fields[IDX_BUF_STATS_POOL_ID]->store(
4563 		static_cast<double>(info->pool_unique_id)));
4564 
4565 	OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(
4566 		static_cast<double>(info->pool_size)));
4567 
4568 	OK(fields[IDX_BUF_STATS_LRU_LEN]->store(
4569 		static_cast<double>(info->lru_len)));
4570 
4571 	OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(
4572 		static_cast<double>(info->old_lru_len)));
4573 
4574 	OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(
4575 		static_cast<double>(info->free_list_len)));
4576 
4577 	OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
4578 		static_cast<double>(info->flush_list_len)));
4579 
4580 	OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(
4581 		static_cast<double>(info->n_pend_unzip)));
4582 
4583 	OK(fields[IDX_BUF_STATS_PENDING_READ]->store(
4584 		static_cast<double>(info->n_pend_reads)));
4585 
4586 	OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(
4587 		static_cast<double>(info->n_pending_flush_lru)));
4588 
4589 	OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(
4590 		static_cast<double>(info->n_pending_flush_list)));
4591 
4592 	OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(
4593 		static_cast<double>(info->n_pages_made_young)));
4594 
4595 	OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
4596 		static_cast<double>(info->n_pages_not_made_young)));
4597 
4598 	OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
4599 		info->page_made_young_rate));
4600 
4601 	OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
4602 		info->page_not_made_young_rate));
4603 
4604 	OK(fields[IDX_BUF_STATS_PAGE_READ]->store(
4605 		static_cast<double>(info->n_pages_read)));
4606 
4607 	OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(
4608 		static_cast<double>(info->n_pages_created)));
4609 
4610 	OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(
4611 		static_cast<double>(info->n_pages_written)));
4612 
4613 	OK(fields[IDX_BUF_STATS_GET]->store(
4614 		static_cast<double>(info->n_page_gets)));
4615 
4616 	OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(
4617 		info->pages_read_rate));
4618 
4619 	OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(
4620 		info->pages_created_rate));
4621 
4622 	OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(
4623 		info->pages_written_rate));
4624 
4625 	if (info->n_page_get_delta) {
4626 		OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
4627 			static_cast<double>(
4628 				1000 - (1000 * info->page_read_delta
4629 				/ info->n_page_get_delta))));
4630 
4631 		OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
4632 			static_cast<double>(
4633 				1000 * info->young_making_delta
4634 				/ info->n_page_get_delta)));
4635 
4636 		OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
4637 			static_cast<double>(
4638 				1000 * info->not_young_making_delta
4639 				/ info->n_page_get_delta)));
4640 	} else {
4641 		OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0));
4642 		OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0));
4643 		OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0));
4644 	}
4645 
4646 	OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(
4647 		static_cast<double>(info->n_ra_pages_read)));
4648 
4649 	OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
4650 		static_cast<double>(info->n_ra_pages_evicted)));
4651 
4652 	OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
4653 		info->pages_readahead_rate));
4654 
4655 	OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
4656 		info->pages_evicted_rate));
4657 
4658 	OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(
4659 		static_cast<double>(info->io_sum)));
4660 
4661 	OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(
4662 		static_cast<double>(info->io_cur)));
4663 
4664 	OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(
4665 		static_cast<double>(info->unzip_sum)));
4666 
4667 	OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store(
4668 		static_cast<double>(info->unzip_cur)));
4669 
4670 	DBUG_RETURN(schema_table_store_record(thd, table));
4671 }
4672 
4673 /*******************************************************************//**
4674 This is the function that loops through each buffer pool and fetch buffer
4675 pool stats to information schema  table: I_S_INNODB_BUFFER_POOL_STATS
4676 @return	0 on success, 1 on failure */
4677 static
4678 int
i_s_innodb_buffer_stats_fill_table(THD * thd,TABLE_LIST * tables,Item *)4679 i_s_innodb_buffer_stats_fill_table(
4680 /*===============================*/
4681 	THD*		thd,		/*!< in: thread */
4682 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
4683 	Item*		)		/*!< in: condition (ignored) */
4684 {
4685 	int			status	= 0;
4686 	buf_pool_info_t*	pool_info;
4687 
4688 	DBUG_ENTER("i_s_innodb_buffer_fill_general");
4689 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
4690 
4691 	/* Only allow the PROCESS privilege holder to access the stats */
4692 	if (check_global_access(thd, PROCESS_ACL)) {
4693 		DBUG_RETURN(0);
4694 	}
4695 
4696 	pool_info = (buf_pool_info_t*) mem_zalloc(
4697 		srv_buf_pool_instances *  sizeof *pool_info);
4698 
4699 	/* Walk through each buffer pool */
4700 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
4701 		buf_pool_t*		buf_pool;
4702 
4703 		buf_pool = buf_pool_from_array(i);
4704 
4705 		/* Fetch individual buffer pool info */
4706 		buf_stats_get_pool_info(buf_pool, i, pool_info);
4707 
4708 		status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
4709 
4710 		/* If something goes wrong, break and return */
4711 		if (status) {
4712 			break;
4713 		}
4714 	}
4715 
4716 	mem_free(pool_info);
4717 
4718 	DBUG_RETURN(status);
4719 }
4720 
4721 /*******************************************************************//**
4722 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
4723 @return	0 on success, 1 on failure */
4724 static
4725 int
i_s_innodb_buffer_pool_stats_init(void * p)4726 i_s_innodb_buffer_pool_stats_init(
4727 /*==============================*/
4728 	void*	p)	/*!< in/out: table schema object */
4729 {
4730 	ST_SCHEMA_TABLE*	schema;
4731 
4732 	DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
4733 
4734 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
4735 
4736 	schema->fields_info = i_s_innodb_buffer_stats_fields_info;
4737 	schema->fill_table = i_s_innodb_buffer_stats_fill_table;
4738 
4739 	DBUG_RETURN(0);
4740 }
4741 
4742 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_buffer_stats =
4743 {
4744 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
4745 	/* int */
4746 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4747 
4748 	/* pointer to type-specific plugin descriptor */
4749 	/* void* */
4750 	STRUCT_FLD(info, &i_s_info),
4751 
4752 	/* plugin name */
4753 	/* const char* */
4754 	STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
4755 
4756 	/* plugin author (for SHOW PLUGINS) */
4757 	/* const char* */
4758 	STRUCT_FLD(author, plugin_author),
4759 
4760 	/* general descriptive text (for SHOW PLUGINS) */
4761 	/* const char* */
4762 	STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
4763 
4764 	/* the plugin license (PLUGIN_LICENSE_XXX) */
4765 	/* int */
4766 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4767 
4768 	/* the function to invoke when plugin is loaded */
4769 	/* int (*)(void*); */
4770 	STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
4771 
4772 	/* the function to invoke when plugin is unloaded */
4773 	/* int (*)(void*); */
4774 	STRUCT_FLD(deinit, i_s_common_deinit),
4775 
4776 	/* plugin version (for SHOW PLUGINS) */
4777 	/* unsigned int */
4778 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
4779 
4780 	/* struct st_mysql_show_var* */
4781 	STRUCT_FLD(status_vars, NULL),
4782 
4783 	/* struct st_mysql_sys_var** */
4784 	STRUCT_FLD(system_vars, NULL),
4785 
4786 	/* reserved for dependency checking */
4787 	/* void* */
4788 	STRUCT_FLD(__reserved1, NULL),
4789 
4790 	/* Plugin flags */
4791 	/* unsigned long */
4792 	STRUCT_FLD(flags, 0UL),
4793 };
4794 
4795 /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
4796 static ST_FIELD_INFO	i_s_innodb_buffer_page_fields_info[] =
4797 {
4798 #define IDX_BUFFER_POOL_ID		0
4799 	{STRUCT_FLD(field_name,		"POOL_ID"),
4800 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4801 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4802 	 STRUCT_FLD(value,		0),
4803 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4804 	 STRUCT_FLD(old_name,		""),
4805 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4806 
4807 #define IDX_BUFFER_BLOCK_ID		1
4808 	{STRUCT_FLD(field_name,		"BLOCK_ID"),
4809 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4810 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4811 	 STRUCT_FLD(value,		0),
4812 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4813 	 STRUCT_FLD(old_name,		""),
4814 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4815 
4816 #define IDX_BUFFER_PAGE_SPACE		2
4817 	{STRUCT_FLD(field_name,		"SPACE"),
4818 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4819 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4820 	 STRUCT_FLD(value,		0),
4821 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4822 	 STRUCT_FLD(old_name,		""),
4823 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4824 
4825 #define IDX_BUFFER_PAGE_NUM		3
4826 	{STRUCT_FLD(field_name,		"PAGE_NUMBER"),
4827 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4828 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4829 	 STRUCT_FLD(value,		0),
4830 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4831 	 STRUCT_FLD(old_name,		""),
4832 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4833 
4834 #define IDX_BUFFER_PAGE_TYPE		4
4835 	{STRUCT_FLD(field_name,		"PAGE_TYPE"),
4836 	 STRUCT_FLD(field_length,	64),
4837 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4838 	 STRUCT_FLD(value,		0),
4839 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4840 	 STRUCT_FLD(old_name,		""),
4841 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4842 
4843 #define IDX_BUFFER_PAGE_FLUSH_TYPE	5
4844 	{STRUCT_FLD(field_name,		"FLUSH_TYPE"),
4845 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4846 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4847 	 STRUCT_FLD(value,		0),
4848 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4849 	 STRUCT_FLD(old_name,		""),
4850 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4851 
4852 #define IDX_BUFFER_PAGE_FIX_COUNT	6
4853 	{STRUCT_FLD(field_name,		"FIX_COUNT"),
4854 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4855 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4856 	 STRUCT_FLD(value,		0),
4857 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4858 	 STRUCT_FLD(old_name,		""),
4859 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4860 
4861 #define IDX_BUFFER_PAGE_HASHED		7
4862 	{STRUCT_FLD(field_name,		"IS_HASHED"),
4863 	 STRUCT_FLD(field_length,	3),
4864 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4865 	 STRUCT_FLD(value,		0),
4866 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4867 	 STRUCT_FLD(old_name,		""),
4868 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4869 
4870 #define IDX_BUFFER_PAGE_NEWEST_MOD	8
4871 	{STRUCT_FLD(field_name,		"NEWEST_MODIFICATION"),
4872 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4873 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4874 	 STRUCT_FLD(value,		0),
4875 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4876 	 STRUCT_FLD(old_name,		""),
4877 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4878 
4879 #define IDX_BUFFER_PAGE_OLDEST_MOD	9
4880 	{STRUCT_FLD(field_name,		"OLDEST_MODIFICATION"),
4881 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4882 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4883 	 STRUCT_FLD(value,		0),
4884 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4885 	 STRUCT_FLD(old_name,		""),
4886 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4887 
4888 #define IDX_BUFFER_PAGE_ACCESS_TIME	10
4889 	{STRUCT_FLD(field_name,		"ACCESS_TIME"),
4890 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4891 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4892 	 STRUCT_FLD(value,		0),
4893 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4894 	 STRUCT_FLD(old_name,		""),
4895 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4896 
4897 #define IDX_BUFFER_PAGE_TABLE_NAME	11
4898 	{STRUCT_FLD(field_name,		"TABLE_NAME"),
4899 	 STRUCT_FLD(field_length,	1024),
4900 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4901 	 STRUCT_FLD(value,		0),
4902 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4903 	 STRUCT_FLD(old_name,		""),
4904 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4905 
4906 #define IDX_BUFFER_PAGE_INDEX_NAME	12
4907 	{STRUCT_FLD(field_name,		"INDEX_NAME"),
4908 	 STRUCT_FLD(field_length,	1024),
4909 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4910 	 STRUCT_FLD(value,		0),
4911 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4912 	 STRUCT_FLD(old_name,		""),
4913 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4914 
4915 #define IDX_BUFFER_PAGE_NUM_RECS	13
4916 	{STRUCT_FLD(field_name,		"NUMBER_RECORDS"),
4917 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4918 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4919 	 STRUCT_FLD(value,		0),
4920 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4921 	 STRUCT_FLD(old_name,		""),
4922 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4923 
4924 #define IDX_BUFFER_PAGE_DATA_SIZE	14
4925 	{STRUCT_FLD(field_name,		"DATA_SIZE"),
4926 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4927 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4928 	 STRUCT_FLD(value,		0),
4929 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4930 	 STRUCT_FLD(old_name,		""),
4931 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4932 
4933 #define IDX_BUFFER_PAGE_ZIP_SIZE	15
4934 	{STRUCT_FLD(field_name,		"COMPRESSED_SIZE"),
4935 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4936 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4937 	 STRUCT_FLD(value,		0),
4938 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4939 	 STRUCT_FLD(old_name,		""),
4940 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4941 
4942 #define IDX_BUFFER_PAGE_STATE		16
4943 	{STRUCT_FLD(field_name,		"PAGE_STATE"),
4944 	 STRUCT_FLD(field_length,	64),
4945 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4946 	 STRUCT_FLD(value,		0),
4947 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4948 	 STRUCT_FLD(old_name,		""),
4949 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4950 
4951 #define IDX_BUFFER_PAGE_IO_FIX		17
4952 	{STRUCT_FLD(field_name,		"IO_FIX"),
4953 	 STRUCT_FLD(field_length,	64),
4954 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4955 	 STRUCT_FLD(value,		0),
4956 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4957 	 STRUCT_FLD(old_name,		""),
4958 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4959 
4960 #define IDX_BUFFER_PAGE_IS_OLD		18
4961 	{STRUCT_FLD(field_name,		"IS_OLD"),
4962 	 STRUCT_FLD(field_length,	3),
4963 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4964 	 STRUCT_FLD(value,		0),
4965 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4966 	 STRUCT_FLD(old_name,		""),
4967 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4968 
4969 #define IDX_BUFFER_PAGE_FREE_CLOCK	19
4970 	{STRUCT_FLD(field_name,		"FREE_PAGE_CLOCK"),
4971 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4972 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4973 	 STRUCT_FLD(value,		0),
4974 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4975 	 STRUCT_FLD(old_name,		""),
4976 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4977 
4978 	END_OF_ST_FIELD_INFO
4979 };
4980 
4981 /*******************************************************************//**
4982 Fill Information Schema table INNODB_BUFFER_PAGE with information
4983 cached in the buf_page_info_t array
4984 @return	0 on success, 1 on failure */
4985 static
4986 int
i_s_innodb_buffer_page_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)4987 i_s_innodb_buffer_page_fill(
4988 /*========================*/
4989 	THD*			thd,		/*!< in: thread */
4990 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
4991 	const buf_page_info_t*	info_array,	/*!< in: array cached page
4992 						info */
4993 	ulint			num_page)	/*!< in: number of page info
4994 						cached */
4995 {
4996 	TABLE*			table;
4997 	Field**			fields;
4998 
4999 	DBUG_ENTER("i_s_innodb_buffer_page_fill");
5000 
5001 	table = tables->table;
5002 
5003 	fields = table->field;
5004 
5005 	/* Iterate through the cached array and fill the I_S table rows */
5006 	for (ulint i = 0; i < num_page; i++) {
5007 		const buf_page_info_t*	page_info;
5008 		char			table_name[MAX_FULL_NAME_LEN + 1];
5009 		const char*		table_name_end = NULL;
5010 		const char*		state_str;
5011 		enum buf_page_state	state;
5012 
5013 		page_info = info_array + i;
5014 
5015 		state_str = NULL;
5016 
5017 		OK(fields[IDX_BUFFER_POOL_ID]->store(
5018 			static_cast<double>(page_info->pool_id)));
5019 
5020 		OK(fields[IDX_BUFFER_BLOCK_ID]->store(
5021 			static_cast<double>(page_info->block_id)));
5022 
5023 		OK(fields[IDX_BUFFER_PAGE_SPACE]->store(
5024 			static_cast<double>(page_info->space_id)));
5025 
5026 		OK(fields[IDX_BUFFER_PAGE_NUM]->store(
5027 			static_cast<double>(page_info->page_num)));
5028 
5029 		OK(field_store_string(
5030 			fields[IDX_BUFFER_PAGE_TYPE],
5031 			i_s_page_type[page_info->page_type].type_str));
5032 
5033 		OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
5034 			page_info->flush_type));
5035 
5036 		OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
5037 			page_info->fix_count));
5038 
5039 		if (page_info->hashed) {
5040 			OK(field_store_string(
5041 				fields[IDX_BUFFER_PAGE_HASHED], "YES"));
5042 		} else {
5043 			OK(field_store_string(
5044 				fields[IDX_BUFFER_PAGE_HASHED], "NO"));
5045 		}
5046 
5047 		OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
5048 			(longlong) page_info->newest_mod, true));
5049 
5050 		OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
5051 			(longlong) page_info->oldest_mod, true));
5052 
5053 		OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
5054 			page_info->access_time));
5055 
5056 		fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_null();
5057 
5058 		fields[IDX_BUFFER_PAGE_INDEX_NAME]->set_null();
5059 
5060 		/* If this is an index page, fetch the index name
5061 		and table name */
5062 		if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
5063 			const dict_index_t*	index;
5064 
5065 			mutex_enter(&dict_sys->mutex);
5066 			index = dict_index_get_if_in_cache_low(
5067 				page_info->index_id);
5068 
5069 			if (index) {
5070 
5071 				table_name_end = innobase_convert_name(
5072 					table_name, sizeof(table_name),
5073 					index->table_name,
5074 					strlen(index->table_name),
5075 					thd, TRUE);
5076 
5077 				OK(fields[IDX_BUFFER_PAGE_TABLE_NAME]->store(
5078 					table_name,
5079 					static_cast<uint>(table_name_end - table_name),
5080 					system_charset_info));
5081 				fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull();
5082 
5083 				OK(field_store_index_name(
5084 					fields[IDX_BUFFER_PAGE_INDEX_NAME],
5085 					index->name));
5086 			}
5087 
5088 			mutex_exit(&dict_sys->mutex);
5089 		}
5090 
5091 		OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
5092 			page_info->num_recs));
5093 
5094 		OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
5095 			page_info->data_size));
5096 
5097 		OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
5098 			page_info->zip_ssize
5099 			? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize
5100 			: 0));
5101 
5102 #if BUF_PAGE_STATE_BITS > 3
5103 # error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
5104 #endif
5105 		state = static_cast<enum buf_page_state>(page_info->page_state);
5106 
5107 		switch (state) {
5108 		/* First three states are for compression pages and
5109 		are not states we would get as we scan pages through
5110 		buffer blocks */
5111 		case BUF_BLOCK_POOL_WATCH:
5112 		case BUF_BLOCK_ZIP_PAGE:
5113 		case BUF_BLOCK_ZIP_DIRTY:
5114 			state_str = NULL;
5115 			break;
5116 		case BUF_BLOCK_NOT_USED:
5117 			state_str = "NOT_USED";
5118 			break;
5119 		case BUF_BLOCK_READY_FOR_USE:
5120 			state_str = "READY_FOR_USE";
5121 			break;
5122 		case BUF_BLOCK_FILE_PAGE:
5123 			state_str = "FILE_PAGE";
5124 			break;
5125 		case BUF_BLOCK_MEMORY:
5126 			state_str = "MEMORY";
5127 			break;
5128 		case BUF_BLOCK_REMOVE_HASH:
5129 			state_str = "REMOVE_HASH";
5130 			break;
5131 		};
5132 
5133 		OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
5134 				      state_str));
5135 
5136 		switch (page_info->io_fix) {
5137 		case BUF_IO_NONE:
5138 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5139 					      "IO_NONE"));
5140 			break;
5141 		case BUF_IO_READ:
5142 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5143 					      "IO_READ"));
5144 			break;
5145 		case BUF_IO_WRITE:
5146 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5147 					      "IO_WRITE"));
5148 			break;
5149 		case BUF_IO_PIN:
5150 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5151 					      "IO_PIN"));
5152 			break;
5153 		}
5154 
5155 		OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
5156 				      (page_info->is_old) ? "YES" : "NO"));
5157 
5158 		OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
5159 			page_info->freed_page_clock));
5160 
5161 		if (schema_table_store_record(thd, table)) {
5162 			DBUG_RETURN(1);
5163 		}
5164 	}
5165 
5166 	DBUG_RETURN(0);
5167 }
5168 
5169 /*******************************************************************//**
5170 Set appropriate page type to a buf_page_info_t structure */
5171 static
5172 void
i_s_innodb_set_page_type(buf_page_info_t * page_info,ulint page_type,const byte * frame)5173 i_s_innodb_set_page_type(
5174 /*=====================*/
5175 	buf_page_info_t*page_info,	/*!< in/out: structure to fill with
5176 					scanned info */
5177 	ulint		page_type,	/*!< in: page type */
5178 	const byte*	frame)		/*!< in: buffer frame */
5179 {
5180 	if (page_type == FIL_PAGE_INDEX) {
5181 		const page_t*	page = (const page_t*) frame;
5182 
5183 		page_info->index_id = btr_page_get_index_id(page);
5184 
5185 		/* FIL_PAGE_INDEX is a bit special, its value
5186 		is defined as 17855, so we cannot use FIL_PAGE_INDEX
5187 		to index into i_s_page_type[] array, its array index
5188 		in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
5189 		(1) for index pages or I_S_PAGE_TYPE_IBUF for
5190 		change buffer index pages */
5191 		if (page_info->index_id
5192 		    == static_cast<index_id_t>(DICT_IBUF_ID_MIN
5193 					       + IBUF_SPACE_ID)) {
5194 			page_info->page_type = I_S_PAGE_TYPE_IBUF;
5195 		} else {
5196 			page_info->page_type = I_S_PAGE_TYPE_INDEX;
5197 		}
5198 
5199 		page_info->data_size = (ulint)(page_header_get_field(
5200 			page, PAGE_HEAP_TOP) - (page_is_comp(page)
5201 						? PAGE_NEW_SUPREMUM_END
5202 						: PAGE_OLD_SUPREMUM_END)
5203 			- page_header_get_field(page, PAGE_GARBAGE));
5204 
5205 		page_info->num_recs = page_get_n_recs(page);
5206 	} else if (page_type > FIL_PAGE_TYPE_LAST) {
5207 		/* Encountered an unknown page type */
5208 		page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5209 	} else {
5210 		/* Make sure we get the right index into the
5211 		i_s_page_type[] array */
5212 		ut_a(page_type == i_s_page_type[page_type].type_value);
5213 
5214 		page_info->page_type = page_type;
5215 	}
5216 
5217 	if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
5218 	    || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
5219 		page_info->page_num = mach_read_from_4(
5220 			frame + FIL_PAGE_OFFSET);
5221 		page_info->space_id = mach_read_from_4(
5222 			frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
5223 	}
5224 }
5225 /*******************************************************************//**
5226 Scans pages in the buffer cache, and collect their general information
5227 into the buf_page_info_t array which is zero-filled. So any fields
5228 that are not initialized in the function will default to 0 */
5229 static
5230 void
i_s_innodb_buffer_page_get_info(const buf_page_t * bpage,ulint pool_id,ulint pos,buf_page_info_t * page_info)5231 i_s_innodb_buffer_page_get_info(
5232 /*============================*/
5233 	const buf_page_t*bpage,		/*!< in: buffer pool page to scan */
5234 	ulint		pool_id,	/*!< in: buffer pool id */
5235 	ulint		pos,		/*!< in: buffer block position in
5236 					buffer pool or in the LRU list */
5237 	buf_page_info_t*page_info)	/*!< in: zero filled info structure;
5238 					out: structure filled with scanned
5239 					info */
5240 {
5241 	ut_ad(pool_id < MAX_BUFFER_POOLS);
5242 
5243 	page_info->pool_id = pool_id;
5244 
5245 	page_info->block_id = pos;
5246 
5247 	page_info->page_state = buf_page_get_state(bpage);
5248 
5249 	/* Only fetch information for buffers that map to a tablespace,
5250 	that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
5251 	BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
5252 	if (buf_page_in_file(bpage)) {
5253 		const byte*	frame;
5254 		ulint		page_type;
5255 
5256 		page_info->space_id = buf_page_get_space(bpage);
5257 
5258 		page_info->page_num = buf_page_get_page_no(bpage);
5259 
5260 		page_info->flush_type = bpage->flush_type;
5261 
5262 		page_info->fix_count = bpage->buf_fix_count;
5263 
5264 		page_info->newest_mod = bpage->newest_modification;
5265 
5266 		page_info->oldest_mod = bpage->oldest_modification;
5267 
5268 		page_info->access_time = bpage->access_time;
5269 
5270 		page_info->zip_ssize = bpage->zip.ssize;
5271 
5272 		page_info->io_fix = bpage->io_fix;
5273 
5274 		page_info->is_old = bpage->old;
5275 
5276 		page_info->freed_page_clock = bpage->freed_page_clock;
5277 
5278 		switch (buf_page_get_io_fix(bpage)) {
5279 		case BUF_IO_NONE:
5280 		case BUF_IO_WRITE:
5281 		case BUF_IO_PIN:
5282 			break;
5283 		case BUF_IO_READ:
5284 			page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5285 			return;
5286 		}
5287 
5288 		if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
5289 			const buf_block_t*block;
5290 
5291 			block = reinterpret_cast<const buf_block_t*>(bpage);
5292 			frame = block->frame;
5293 			page_info->hashed = (block->index != NULL);
5294 		} else {
5295 			ut_ad(page_info->zip_ssize);
5296 			frame = bpage->zip.data;
5297 		}
5298 
5299 		page_type = fil_page_get_type(frame);
5300 
5301 		i_s_innodb_set_page_type(page_info, page_type, frame);
5302 	} else {
5303 		page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5304 	}
5305 }
5306 
5307 /*******************************************************************//**
5308 This is the function that goes through each block of the buffer pool
5309 and fetch information to information schema tables: INNODB_BUFFER_PAGE.
5310 @return	0 on success, 1 on failure */
5311 static
5312 int
i_s_innodb_fill_buffer_pool(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)5313 i_s_innodb_fill_buffer_pool(
5314 /*========================*/
5315 	THD*			thd,		/*!< in: thread */
5316 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
5317 	buf_pool_t*		buf_pool,	/*!< in: buffer pool to scan */
5318 	const ulint		pool_id)	/*!< in: buffer pool id */
5319 {
5320 	int			status	= 0;
5321 	mem_heap_t*		heap;
5322 
5323 	DBUG_ENTER("i_s_innodb_fill_buffer_pool");
5324 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
5325 
5326 	heap = mem_heap_create(10000);
5327 
5328 	/* Go through each chunk of buffer pool. Currently, we only
5329 	have one single chunk for each buffer pool */
5330 	for (ulint n = 0; n < buf_pool->n_chunks; n++) {
5331 		const buf_block_t*	block;
5332 		ulint			n_blocks;
5333 		buf_page_info_t*	info_buffer;
5334 		ulint			num_page;
5335 		ulint			mem_size;
5336 		ulint			chunk_size;
5337 		ulint			num_to_process = 0;
5338 		ulint			block_id = 0;
5339 
5340 		/* Get buffer block of the nth chunk */
5341 		block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
5342 		num_page = 0;
5343 
5344 		while (chunk_size > 0) {
5345 			/* we cache maximum MAX_BUF_INFO_CACHED number of
5346 			buffer page info */
5347 			num_to_process = ut_min(chunk_size,
5348 						MAX_BUF_INFO_CACHED);
5349 
5350 			mem_size = num_to_process * sizeof(buf_page_info_t);
5351 
5352 			/* For each chunk, we'll pre-allocate information
5353 			structures to cache the page information read from
5354 			the buffer pool. Doing so before obtain any mutex */
5355 			info_buffer = (buf_page_info_t*) mem_heap_zalloc(
5356 				heap, mem_size);
5357 
5358 			/* Obtain appropriate mutexes. Since this is diagnostic
5359 			buffer pool info printout, we are not required to
5360 			preserve the overall consistency, so we can
5361 			release mutex periodically */
5362 			buf_pool_mutex_enter(buf_pool);
5363 
5364 			/* GO through each block in the chunk */
5365 			for (n_blocks = num_to_process; n_blocks--; block++) {
5366 				i_s_innodb_buffer_page_get_info(
5367 					&block->page, pool_id, block_id,
5368 					info_buffer + num_page);
5369 				block_id++;
5370 				num_page++;
5371 			}
5372 
5373 			buf_pool_mutex_exit(buf_pool);
5374 
5375 			/* Fill in information schema table with information
5376 			just collected from the buffer chunk scan */
5377 			status = i_s_innodb_buffer_page_fill(
5378 				thd, tables, info_buffer,
5379 				num_page);
5380 
5381 			/* If something goes wrong, break and return */
5382 			if (status) {
5383 				break;
5384 			}
5385 
5386 			mem_heap_empty(heap);
5387 			chunk_size -= num_to_process;
5388 			num_page = 0;
5389 		}
5390 	}
5391 
5392 	mem_heap_free(heap);
5393 
5394 	DBUG_RETURN(status);
5395 }
5396 
5397 /*******************************************************************//**
5398 Fill page information for pages in InnoDB buffer pool to the
5399 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
5400 @return	0 on success, 1 on failure */
5401 static
5402 int
i_s_innodb_buffer_page_fill_table(THD * thd,TABLE_LIST * tables,Item *)5403 i_s_innodb_buffer_page_fill_table(
5404 /*==============================*/
5405 	THD*		thd,		/*!< in: thread */
5406 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
5407 	Item*		)		/*!< in: condition (ignored) */
5408 {
5409 	int	status	= 0;
5410 
5411 	DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
5412 
5413 	/* deny access to user without PROCESS privilege */
5414 	if (check_global_access(thd, PROCESS_ACL)) {
5415 		DBUG_RETURN(0);
5416 	}
5417 
5418 	/* Walk through each buffer pool */
5419 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
5420 		buf_pool_t*	buf_pool;
5421 
5422 		buf_pool = buf_pool_from_array(i);
5423 
5424 		/* Fetch information from pages in this buffer pool,
5425 		and fill the corresponding I_S table */
5426 		status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
5427 
5428 		/* If something wrong, break and return */
5429 		if (status) {
5430 			break;
5431 		}
5432 	}
5433 
5434 	DBUG_RETURN(status);
5435 }
5436 
5437 /*******************************************************************//**
5438 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
5439 @return	0 on success, 1 on failure */
5440 static
5441 int
i_s_innodb_buffer_page_init(void * p)5442 i_s_innodb_buffer_page_init(
5443 /*========================*/
5444 	void*	p)	/*!< in/out: table schema object */
5445 {
5446 	ST_SCHEMA_TABLE*	schema;
5447 
5448 	DBUG_ENTER("i_s_innodb_buffer_page_init");
5449 
5450 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
5451 
5452 	schema->fields_info = i_s_innodb_buffer_page_fields_info;
5453 	schema->fill_table = i_s_innodb_buffer_page_fill_table;
5454 
5455 	DBUG_RETURN(0);
5456 }
5457 
5458 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_buffer_page =
5459 {
5460 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
5461 	/* int */
5462 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
5463 
5464 	/* pointer to type-specific plugin descriptor */
5465 	/* void* */
5466 	STRUCT_FLD(info, &i_s_info),
5467 
5468 	/* plugin name */
5469 	/* const char* */
5470 	STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
5471 
5472 	/* plugin author (for SHOW PLUGINS) */
5473 	/* const char* */
5474 	STRUCT_FLD(author, plugin_author),
5475 
5476 	/* general descriptive text (for SHOW PLUGINS) */
5477 	/* const char* */
5478 	STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
5479 
5480 	/* the plugin license (PLUGIN_LICENSE_XXX) */
5481 	/* int */
5482 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
5483 
5484 	/* the function to invoke when plugin is loaded */
5485 	/* int (*)(void*); */
5486 	STRUCT_FLD(init, i_s_innodb_buffer_page_init),
5487 
5488 	/* the function to invoke when plugin is unloaded */
5489 	/* int (*)(void*); */
5490 	STRUCT_FLD(deinit, i_s_common_deinit),
5491 
5492 	/* plugin version (for SHOW PLUGINS) */
5493 	/* unsigned int */
5494 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
5495 
5496 	/* struct st_mysql_show_var* */
5497 	STRUCT_FLD(status_vars, NULL),
5498 
5499 	/* struct st_mysql_sys_var** */
5500 	STRUCT_FLD(system_vars, NULL),
5501 
5502 	/* reserved for dependency checking */
5503 	/* void* */
5504 	STRUCT_FLD(__reserved1, NULL),
5505 
5506 	/* Plugin flags */
5507 	/* unsigned long */
5508 	STRUCT_FLD(flags, 0UL),
5509 };
5510 
5511 static ST_FIELD_INFO	i_s_innodb_buf_page_lru_fields_info[] =
5512 {
5513 #define IDX_BUF_LRU_POOL_ID		0
5514 	{STRUCT_FLD(field_name,		"POOL_ID"),
5515 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5516 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5517 	 STRUCT_FLD(value,		0),
5518 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5519 	 STRUCT_FLD(old_name,		""),
5520 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5521 
5522 #define IDX_BUF_LRU_POS			1
5523 	{STRUCT_FLD(field_name,		"LRU_POSITION"),
5524 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5525 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5526 	 STRUCT_FLD(value,		0),
5527 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5528 	 STRUCT_FLD(old_name,		""),
5529 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5530 
5531 #define IDX_BUF_LRU_PAGE_SPACE		2
5532 	{STRUCT_FLD(field_name,		"SPACE"),
5533 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5534 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5535 	 STRUCT_FLD(value,		0),
5536 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5537 	 STRUCT_FLD(old_name,		""),
5538 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5539 
5540 #define IDX_BUF_LRU_PAGE_NUM		3
5541 	{STRUCT_FLD(field_name,		"PAGE_NUMBER"),
5542 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5543 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5544 	 STRUCT_FLD(value,		0),
5545 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5546 	 STRUCT_FLD(old_name,		""),
5547 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5548 
5549 #define IDX_BUF_LRU_PAGE_TYPE		4
5550 	{STRUCT_FLD(field_name,		"PAGE_TYPE"),
5551 	 STRUCT_FLD(field_length,	64),
5552 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5553 	 STRUCT_FLD(value,		0),
5554 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5555 	 STRUCT_FLD(old_name,		""),
5556 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5557 
5558 #define IDX_BUF_LRU_PAGE_FLUSH_TYPE	5
5559 	{STRUCT_FLD(field_name,		"FLUSH_TYPE"),
5560 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5561 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5562 	 STRUCT_FLD(value,		0),
5563 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5564 	 STRUCT_FLD(old_name,		""),
5565 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5566 
5567 #define IDX_BUF_LRU_PAGE_FIX_COUNT	6
5568 	{STRUCT_FLD(field_name,		"FIX_COUNT"),
5569 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5570 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5571 	 STRUCT_FLD(value,		0),
5572 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5573 	 STRUCT_FLD(old_name,		""),
5574 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5575 
5576 #define IDX_BUF_LRU_PAGE_HASHED		7
5577 	{STRUCT_FLD(field_name,		"IS_HASHED"),
5578 	 STRUCT_FLD(field_length,	3),
5579 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5580 	 STRUCT_FLD(value,		0),
5581 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5582 	 STRUCT_FLD(old_name,		""),
5583 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5584 
5585 #define IDX_BUF_LRU_PAGE_NEWEST_MOD	8
5586 	{STRUCT_FLD(field_name,		"NEWEST_MODIFICATION"),
5587 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5588 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5589 	 STRUCT_FLD(value,		0),
5590 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5591 	 STRUCT_FLD(old_name,		""),
5592 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5593 
5594 #define IDX_BUF_LRU_PAGE_OLDEST_MOD	9
5595 	{STRUCT_FLD(field_name,		"OLDEST_MODIFICATION"),
5596 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5597 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5598 	 STRUCT_FLD(value,		0),
5599 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5600 	 STRUCT_FLD(old_name,		""),
5601 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5602 
5603 #define IDX_BUF_LRU_PAGE_ACCESS_TIME	10
5604 	{STRUCT_FLD(field_name,		"ACCESS_TIME"),
5605 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5606 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5607 	 STRUCT_FLD(value,		0),
5608 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5609 	 STRUCT_FLD(old_name,		""),
5610 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5611 
5612 #define IDX_BUF_LRU_PAGE_TABLE_NAME	11
5613 	{STRUCT_FLD(field_name,		"TABLE_NAME"),
5614 	 STRUCT_FLD(field_length,	1024),
5615 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5616 	 STRUCT_FLD(value,		0),
5617 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5618 	 STRUCT_FLD(old_name,		""),
5619 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5620 
5621 #define IDX_BUF_LRU_PAGE_INDEX_NAME	12
5622 	{STRUCT_FLD(field_name,		"INDEX_NAME"),
5623 	 STRUCT_FLD(field_length,	1024),
5624 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5625 	 STRUCT_FLD(value,		0),
5626 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5627 	 STRUCT_FLD(old_name,		""),
5628 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5629 
5630 #define IDX_BUF_LRU_PAGE_NUM_RECS	13
5631 	{STRUCT_FLD(field_name,		"NUMBER_RECORDS"),
5632 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5633 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5634 	 STRUCT_FLD(value,		0),
5635 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5636 	 STRUCT_FLD(old_name,		""),
5637 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5638 
5639 #define IDX_BUF_LRU_PAGE_DATA_SIZE	14
5640 	{STRUCT_FLD(field_name,		"DATA_SIZE"),
5641 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5642 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5643 	 STRUCT_FLD(value,		0),
5644 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5645 	 STRUCT_FLD(old_name,		""),
5646 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5647 
5648 #define IDX_BUF_LRU_PAGE_ZIP_SIZE	15
5649 	{STRUCT_FLD(field_name,		"COMPRESSED_SIZE"),
5650 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5651 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5652 	 STRUCT_FLD(value,		0),
5653 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5654 	 STRUCT_FLD(old_name,		""),
5655 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5656 
5657 #define IDX_BUF_LRU_PAGE_STATE		16
5658 	{STRUCT_FLD(field_name,		"COMPRESSED"),
5659 	 STRUCT_FLD(field_length,	3),
5660 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5661 	 STRUCT_FLD(value,		0),
5662 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5663 	 STRUCT_FLD(old_name,		""),
5664 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5665 
5666 #define IDX_BUF_LRU_PAGE_IO_FIX		17
5667 	{STRUCT_FLD(field_name,		"IO_FIX"),
5668 	 STRUCT_FLD(field_length,	64),
5669 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5670 	 STRUCT_FLD(value,		0),
5671 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5672 	 STRUCT_FLD(old_name,		""),
5673 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5674 
5675 #define IDX_BUF_LRU_PAGE_IS_OLD		18
5676 	{STRUCT_FLD(field_name,		"IS_OLD"),
5677 	 STRUCT_FLD(field_length,	3),
5678 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5679 	 STRUCT_FLD(value,		0),
5680 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5681 	 STRUCT_FLD(old_name,		""),
5682 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5683 
5684 #define IDX_BUF_LRU_PAGE_FREE_CLOCK	19
5685 	{STRUCT_FLD(field_name,		"FREE_PAGE_CLOCK"),
5686 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5687 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5688 	 STRUCT_FLD(value,		0),
5689 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5690 	 STRUCT_FLD(old_name,		""),
5691 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5692 
5693 	END_OF_ST_FIELD_INFO
5694 };
5695 
5696 /*******************************************************************//**
5697 Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
5698 cached in the buf_page_info_t array
5699 @return	0 on success, 1 on failure */
5700 static
5701 int
i_s_innodb_buf_page_lru_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)5702 i_s_innodb_buf_page_lru_fill(
5703 /*=========================*/
5704 	THD*			thd,		/*!< in: thread */
5705 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
5706 	const buf_page_info_t*	info_array,	/*!< in: array cached page
5707 						info */
5708 	ulint			num_page)	/*!< in: number of page info
5709 						 cached */
5710 {
5711 	TABLE*			table;
5712 	Field**			fields;
5713 	mem_heap_t*		heap;
5714 
5715 	DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
5716 
5717 	table = tables->table;
5718 
5719 	fields = table->field;
5720 
5721 	heap = mem_heap_create(1000);
5722 
5723 	/* Iterate through the cached array and fill the I_S table rows */
5724 	for (ulint i = 0; i < num_page; i++) {
5725 		const buf_page_info_t*	page_info;
5726 		char			table_name[MAX_FULL_NAME_LEN + 1];
5727 		const char*		table_name_end = NULL;
5728 		const char*		state_str;
5729 		enum buf_page_state	state;
5730 
5731 		state_str = NULL;
5732 
5733 		page_info = info_array + i;
5734 
5735 		OK(fields[IDX_BUF_LRU_POOL_ID]->store(
5736 			static_cast<double>(page_info->pool_id)));
5737 
5738 		OK(fields[IDX_BUF_LRU_POS]->store(
5739 			static_cast<double>(page_info->block_id)));
5740 
5741 		OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(
5742 			static_cast<double>(page_info->space_id)));
5743 
5744 		OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(
5745 			static_cast<double>(page_info->page_num)));
5746 
5747 		OK(field_store_string(
5748 			fields[IDX_BUF_LRU_PAGE_TYPE],
5749 			i_s_page_type[page_info->page_type].type_str));
5750 
5751 		OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
5752 			static_cast<double>(page_info->flush_type)));
5753 
5754 		OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
5755 			static_cast<double>(page_info->fix_count)));
5756 
5757 		if (page_info->hashed) {
5758 			OK(field_store_string(
5759 				fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
5760 		} else {
5761 			OK(field_store_string(
5762 				fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
5763 		}
5764 
5765 		OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
5766 			page_info->newest_mod, true));
5767 
5768 		OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
5769 			page_info->oldest_mod, true));
5770 
5771 		OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
5772 			page_info->access_time));
5773 
5774 		fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_null();
5775 
5776 		fields[IDX_BUF_LRU_PAGE_INDEX_NAME]->set_null();
5777 
5778 		/* If this is an index page, fetch the index name
5779 		and table name */
5780 		if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
5781 			const dict_index_t*	index;
5782 
5783 			mutex_enter(&dict_sys->mutex);
5784 			index = dict_index_get_if_in_cache_low(
5785 				page_info->index_id);
5786 
5787 			if (index) {
5788 
5789 				table_name_end = innobase_convert_name(
5790 					table_name, sizeof(table_name),
5791 					index->table_name,
5792 					strlen(index->table_name),
5793 					thd, TRUE);
5794 
5795 				OK(fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->store(
5796 					table_name,
5797 					static_cast<uint>(table_name_end - table_name),
5798 					system_charset_info));
5799 				fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull();
5800 
5801 				OK(field_store_index_name(
5802 					fields[IDX_BUF_LRU_PAGE_INDEX_NAME],
5803 					index->name));
5804 			}
5805 
5806 			mutex_exit(&dict_sys->mutex);
5807 		}
5808 
5809 		OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
5810 			page_info->num_recs));
5811 
5812 		OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
5813 			page_info->data_size));
5814 
5815 		OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
5816 			page_info->zip_ssize ?
5817 				 512 << page_info->zip_ssize : 0));
5818 
5819 		state = static_cast<enum buf_page_state>(page_info->page_state);
5820 
5821 		switch (state) {
5822 		/* Compressed page */
5823 		case BUF_BLOCK_ZIP_PAGE:
5824 		case BUF_BLOCK_ZIP_DIRTY:
5825 			state_str = "YES";
5826 			break;
5827 		/* Uncompressed page */
5828 		case BUF_BLOCK_FILE_PAGE:
5829 			state_str = "NO";
5830 			break;
5831 		/* We should not see following states */
5832 		case BUF_BLOCK_POOL_WATCH:
5833 		case BUF_BLOCK_READY_FOR_USE:
5834 		case BUF_BLOCK_NOT_USED:
5835 		case BUF_BLOCK_MEMORY:
5836 		case BUF_BLOCK_REMOVE_HASH:
5837 			state_str = NULL;
5838 			break;
5839 		};
5840 
5841 		OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
5842 				      state_str));
5843 
5844 		switch (page_info->io_fix) {
5845 		case BUF_IO_NONE:
5846 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
5847 					      "IO_NONE"));
5848 			break;
5849 		case BUF_IO_READ:
5850 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
5851 					      "IO_READ"));
5852 			break;
5853 		case BUF_IO_WRITE:
5854 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
5855 					      "IO_WRITE"));
5856 			break;
5857 		}
5858 
5859 		OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
5860 				      (page_info->is_old) ? "YES" : "NO"));
5861 
5862 		OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
5863 			page_info->freed_page_clock));
5864 
5865 		if (schema_table_store_record(thd, table)) {
5866 			mem_heap_free(heap);
5867 			DBUG_RETURN(1);
5868 		}
5869 
5870 		mem_heap_empty(heap);
5871 	}
5872 
5873 	mem_heap_free(heap);
5874 
5875 	DBUG_RETURN(0);
5876 }
5877 
5878 /*******************************************************************//**
5879 This is the function that goes through buffer pool's LRU list
5880 and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
5881 @return	0 on success, 1 on failure */
5882 static
5883 int
i_s_innodb_fill_buffer_lru(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)5884 i_s_innodb_fill_buffer_lru(
5885 /*=======================*/
5886 	THD*			thd,		/*!< in: thread */
5887 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
5888 	buf_pool_t*		buf_pool,	/*!< in: buffer pool to scan */
5889 	const ulint		pool_id)	/*!< in: buffer pool id */
5890 {
5891 	int			status = 0;
5892 	buf_page_info_t*	info_buffer;
5893 	ulint			lru_pos = 0;
5894 	const buf_page_t*	bpage;
5895 	ulint			lru_len;
5896 
5897 	DBUG_ENTER("i_s_innodb_fill_buffer_lru");
5898 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
5899 
5900 	/* Obtain buf_pool mutex before allocate info_buffer, since
5901 	UT_LIST_GET_LEN(buf_pool->LRU) could change */
5902 	buf_pool_mutex_enter(buf_pool);
5903 
5904 	lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
5905 
5906 	/* Print error message if malloc fail */
5907 	info_buffer = (buf_page_info_t*) my_malloc(
5908 		lru_len * sizeof *info_buffer, MYF(MY_WME));
5909 
5910 	if (!info_buffer) {
5911 		status = 1;
5912 		goto exit;
5913 	}
5914 
5915 	memset(info_buffer, 0, lru_len * sizeof *info_buffer);
5916 
5917 	/* Walk through Pool's LRU list and print the buffer page
5918 	information */
5919 	bpage = UT_LIST_GET_LAST(buf_pool->LRU);
5920 
5921 	while (bpage != NULL) {
5922 		/* Use the same function that collect buffer info for
5923 		INNODB_BUFFER_PAGE to get buffer page info */
5924 		i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
5925 						(info_buffer + lru_pos));
5926 
5927 		bpage = UT_LIST_GET_PREV(LRU, bpage);
5928 
5929 		lru_pos++;
5930 	}
5931 
5932 	ut_ad(lru_pos == lru_len);
5933 	ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
5934 
5935 exit:
5936 	buf_pool_mutex_exit(buf_pool);
5937 
5938 	if (info_buffer) {
5939 		status = i_s_innodb_buf_page_lru_fill(
5940 			thd, tables, info_buffer, lru_len);
5941 
5942 		my_free(info_buffer);
5943 	}
5944 
5945 	DBUG_RETURN(status);
5946 }
5947 
5948 /*******************************************************************//**
5949 Fill page information for pages in InnoDB buffer pool to the
5950 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
5951 @return	0 on success, 1 on failure */
5952 static
5953 int
i_s_innodb_buf_page_lru_fill_table(THD * thd,TABLE_LIST * tables,Item *)5954 i_s_innodb_buf_page_lru_fill_table(
5955 /*===============================*/
5956 	THD*		thd,		/*!< in: thread */
5957 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
5958 	Item*		)		/*!< in: condition (ignored) */
5959 {
5960 	int	status	= 0;
5961 
5962 	DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
5963 
5964 	/* deny access to any users that do not hold PROCESS_ACL */
5965 	if (check_global_access(thd, PROCESS_ACL)) {
5966 		DBUG_RETURN(0);
5967 	}
5968 
5969 	/* Walk through each buffer pool */
5970 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
5971 		buf_pool_t*	buf_pool;
5972 
5973 		buf_pool = buf_pool_from_array(i);
5974 
5975 		/* Fetch information from pages in this buffer pool's LRU list,
5976 		and fill the corresponding I_S table */
5977 		status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
5978 
5979 		/* If something wrong, break and return */
5980 		if (status) {
5981 			break;
5982 		}
5983 	}
5984 
5985 	DBUG_RETURN(status);
5986 }
5987 
5988 /*******************************************************************//**
5989 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
5990 @return	0 on success, 1 on failure */
5991 static
5992 int
i_s_innodb_buffer_page_lru_init(void * p)5993 i_s_innodb_buffer_page_lru_init(
5994 /*============================*/
5995 	void*	p)	/*!< in/out: table schema object */
5996 {
5997 	ST_SCHEMA_TABLE*	schema;
5998 
5999 	DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
6000 
6001 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
6002 
6003 	schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
6004 	schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
6005 
6006 	DBUG_RETURN(0);
6007 }
6008 
6009 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_buffer_page_lru =
6010 {
6011 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
6012 	/* int */
6013 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6014 
6015 	/* pointer to type-specific plugin descriptor */
6016 	/* void* */
6017 	STRUCT_FLD(info, &i_s_info),
6018 
6019 	/* plugin name */
6020 	/* const char* */
6021 	STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
6022 
6023 	/* plugin author (for SHOW PLUGINS) */
6024 	/* const char* */
6025 	STRUCT_FLD(author, plugin_author),
6026 
6027 	/* general descriptive text (for SHOW PLUGINS) */
6028 	/* const char* */
6029 	STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
6030 
6031 	/* the plugin license (PLUGIN_LICENSE_XXX) */
6032 	/* int */
6033 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6034 
6035 	/* the function to invoke when plugin is loaded */
6036 	/* int (*)(void*); */
6037 	STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
6038 
6039 	/* the function to invoke when plugin is unloaded */
6040 	/* int (*)(void*); */
6041 	STRUCT_FLD(deinit, i_s_common_deinit),
6042 
6043 	/* plugin version (for SHOW PLUGINS) */
6044 	/* unsigned int */
6045 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
6046 
6047 	/* struct st_mysql_show_var* */
6048 	STRUCT_FLD(status_vars, NULL),
6049 
6050 	/* struct st_mysql_sys_var** */
6051 	STRUCT_FLD(system_vars, NULL),
6052 
6053 	/* reserved for dependency checking */
6054 	/* void* */
6055 	STRUCT_FLD(__reserved1, NULL),
6056 
6057 	/* Plugin flags */
6058 	/* unsigned long */
6059 	STRUCT_FLD(flags, 0UL),
6060 };
6061 
6062 /*******************************************************************//**
6063 Unbind a dynamic INFORMATION_SCHEMA table.
6064 @return	0 on success */
6065 static
6066 int
i_s_common_deinit(void * p)6067 i_s_common_deinit(
6068 /*==============*/
6069 	void*	p)	/*!< in/out: table schema object */
6070 {
6071 	DBUG_ENTER("i_s_common_deinit");
6072 
6073 	/* Do nothing */
6074 
6075 	DBUG_RETURN(0);
6076 }
6077 
6078 /**  SYS_TABLES  ***************************************************/
6079 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLES */
6080 static ST_FIELD_INFO	innodb_sys_tables_fields_info[] =
6081 {
6082 #define SYS_TABLES_ID			0
6083 	{STRUCT_FLD(field_name,		"TABLE_ID"),
6084 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6085 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6086 	 STRUCT_FLD(value,		0),
6087 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6088 	 STRUCT_FLD(old_name,		""),
6089 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6090 
6091 #define SYS_TABLES_NAME			1
6092 	{STRUCT_FLD(field_name,		"NAME"),
6093 	 STRUCT_FLD(field_length,	MAX_FULL_NAME_LEN + 1),
6094 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6095 	 STRUCT_FLD(value,		0),
6096 	 STRUCT_FLD(field_flags,	0),
6097 	 STRUCT_FLD(old_name,		""),
6098 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6099 
6100 #define SYS_TABLES_FLAG			2
6101 	{STRUCT_FLD(field_name,		"FLAG"),
6102 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6103 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6104 	 STRUCT_FLD(value,		0),
6105 	 STRUCT_FLD(field_flags,	0),
6106 	 STRUCT_FLD(old_name,		""),
6107 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6108 
6109 #define SYS_TABLES_NUM_COLUMN		3
6110 	{STRUCT_FLD(field_name,		"N_COLS"),
6111 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6112 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6113 	 STRUCT_FLD(value,		0),
6114 	 STRUCT_FLD(field_flags,	0),
6115 	 STRUCT_FLD(old_name,		""),
6116 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6117 
6118 #define SYS_TABLES_SPACE		4
6119 	{STRUCT_FLD(field_name,		"SPACE"),
6120 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6121 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6122 	 STRUCT_FLD(value,		0),
6123 	 STRUCT_FLD(field_flags,	0),
6124 	 STRUCT_FLD(old_name,		""),
6125 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6126 
6127 #define SYS_TABLES_FILE_FORMAT		5
6128 	{STRUCT_FLD(field_name,		"FILE_FORMAT"),
6129 	 STRUCT_FLD(field_length,	10),
6130 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6131 	 STRUCT_FLD(value,		0),
6132 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
6133 	 STRUCT_FLD(old_name,		""),
6134 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6135 
6136 #define SYS_TABLES_ROW_FORMAT		6
6137 	{STRUCT_FLD(field_name,		"ROW_FORMAT"),
6138 	 STRUCT_FLD(field_length,	12),
6139 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6140 	 STRUCT_FLD(value,		0),
6141 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
6142 	 STRUCT_FLD(old_name,		""),
6143 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6144 
6145 #define SYS_TABLES_ZIP_PAGE_SIZE	7
6146 	{STRUCT_FLD(field_name,		"ZIP_PAGE_SIZE"),
6147 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6148 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6149 	 STRUCT_FLD(value,		0),
6150 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6151 	 STRUCT_FLD(old_name,		""),
6152 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6153 
6154 	END_OF_ST_FIELD_INFO
6155 };
6156 
6157 /**********************************************************************//**
6158 Populate information_schema.innodb_sys_tables table with information
6159 from SYS_TABLES.
6160 @return	0 on success */
6161 static
6162 int
i_s_dict_fill_sys_tables(THD * thd,dict_table_t * table,TABLE * table_to_fill)6163 i_s_dict_fill_sys_tables(
6164 /*=====================*/
6165 	THD*		thd,		/*!< in: thread */
6166 	dict_table_t*	table,		/*!< in: table */
6167 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
6168 {
6169 	Field**		fields;
6170 	ulint	compact		= DICT_TF_GET_COMPACT(table->flags);
6171 	ulint	atomic_blobs	= DICT_TF_HAS_ATOMIC_BLOBS(table->flags);
6172 	ulint	zip_size	= dict_tf_get_zip_size(table->flags);
6173 	const char* file_format;
6174 	const char* row_format;
6175 
6176 	file_format = trx_sys_file_format_id_to_name(atomic_blobs);
6177 	if (!compact) {
6178 		row_format = "Redundant";
6179 	} else if (!atomic_blobs) {
6180 		row_format = "Compact";
6181 	} else if DICT_TF_GET_ZIP_SSIZE(table->flags) {
6182 		row_format = "Compressed";
6183 	} else {
6184 		row_format = "Dynamic";
6185 	}
6186 
6187 	DBUG_ENTER("i_s_dict_fill_sys_tables");
6188 
6189 	fields = table_to_fill->field;
6190 
6191 	OK(fields[SYS_TABLES_ID]->store(longlong(table->id), TRUE));
6192 
6193 	OK(field_store_string(fields[SYS_TABLES_NAME], table->name));
6194 
6195 	OK(fields[SYS_TABLES_FLAG]->store(table->flags));
6196 
6197 	OK(fields[SYS_TABLES_NUM_COLUMN]->store(table->n_cols));
6198 
6199 	OK(fields[SYS_TABLES_SPACE]->store(table->space));
6200 
6201 	OK(field_store_string(fields[SYS_TABLES_FILE_FORMAT], file_format));
6202 
6203 	OK(field_store_string(fields[SYS_TABLES_ROW_FORMAT], row_format));
6204 
6205 	OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(
6206 		static_cast<double>(zip_size)));
6207 
6208 	OK(schema_table_store_record(thd, table_to_fill));
6209 
6210 	DBUG_RETURN(0);
6211 }
6212 /*******************************************************************//**
6213 Function to go through each record in SYS_TABLES table, and fill the
6214 information_schema.innodb_sys_tables table with related table information
6215 @return 0 on success */
6216 static
6217 int
i_s_sys_tables_fill_table(THD * thd,TABLE_LIST * tables,Item *)6218 i_s_sys_tables_fill_table(
6219 /*======================*/
6220 	THD*		thd,	/*!< in: thread */
6221 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
6222 	Item*		)	/*!< in: condition (not used) */
6223 {
6224 	btr_pcur_t	pcur;
6225 	const rec_t*	rec;
6226 	mem_heap_t*	heap;
6227 	mtr_t		mtr;
6228 
6229 	DBUG_ENTER("i_s_sys_tables_fill_table");
6230 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6231 
6232 	/* deny access to user without PROCESS_ACL privilege */
6233 	if (check_global_access(thd, PROCESS_ACL)) {
6234 		DBUG_RETURN(0);
6235 	}
6236 
6237 	heap = mem_heap_create(1000);
6238 	mutex_enter(&(dict_sys->mutex));
6239 	mtr_start(&mtr);
6240 
6241 	rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6242 
6243 	while (rec) {
6244 		const char*	err_msg;
6245 		dict_table_t*	table_rec;
6246 
6247 		/* Create and populate a dict_table_t structure with
6248 		information from SYS_TABLES row */
6249 		err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6250 			heap, rec, &table_rec,
6251 			DICT_TABLE_LOAD_FROM_RECORD, &mtr);
6252 
6253 		mutex_exit(&dict_sys->mutex);
6254 
6255 		if (!err_msg) {
6256 			i_s_dict_fill_sys_tables(thd, table_rec, tables->table);
6257 		} else {
6258 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
6259 					    ER_CANT_FIND_SYSTEM_REC, "%s",
6260 					    err_msg);
6261 		}
6262 
6263 		/* Since dict_process_sys_tables_rec_and_mtr_commit()
6264 		is called with DICT_TABLE_LOAD_FROM_RECORD, the table_rec
6265 		is created in dict_process_sys_tables_rec(), we will
6266 		need to free it */
6267 		if (table_rec) {
6268 			dict_mem_table_free(table_rec);
6269 		}
6270 
6271 		mem_heap_empty(heap);
6272 
6273 		/* Get the next record */
6274 		mutex_enter(&dict_sys->mutex);
6275 		mtr_start(&mtr);
6276 		rec = dict_getnext_system(&pcur, &mtr);
6277 	}
6278 
6279 	mtr_commit(&mtr);
6280 	mutex_exit(&dict_sys->mutex);
6281 	mem_heap_free(heap);
6282 
6283 	DBUG_RETURN(0);
6284 }
6285 
6286 /*******************************************************************//**
6287 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tables
6288 @return 0 on success */
6289 static
6290 int
innodb_sys_tables_init(void * p)6291 innodb_sys_tables_init(
6292 /*===================*/
6293 	void*	p)	/*!< in/out: table schema object */
6294 {
6295 	ST_SCHEMA_TABLE*	schema;
6296 
6297 	DBUG_ENTER("innodb_sys_tables_init");
6298 
6299 	schema = (ST_SCHEMA_TABLE*) p;
6300 
6301 	schema->fields_info = innodb_sys_tables_fields_info;
6302 	schema->fill_table = i_s_sys_tables_fill_table;
6303 
6304 	DBUG_RETURN(0);
6305 }
6306 
6307 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_tables =
6308 {
6309 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
6310 	/* int */
6311 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6312 
6313 	/* pointer to type-specific plugin descriptor */
6314 	/* void* */
6315 	STRUCT_FLD(info, &i_s_info),
6316 
6317 	/* plugin name */
6318 	/* const char* */
6319 	STRUCT_FLD(name, "INNODB_SYS_TABLES"),
6320 
6321 	/* plugin author (for SHOW PLUGINS) */
6322 	/* const char* */
6323 	STRUCT_FLD(author, plugin_author),
6324 
6325 	/* general descriptive text (for SHOW PLUGINS) */
6326 	/* const char* */
6327 	STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
6328 
6329 	/* the plugin license (PLUGIN_LICENSE_XXX) */
6330 	/* int */
6331 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6332 
6333 	/* the function to invoke when plugin is loaded */
6334 	/* int (*)(void*); */
6335 	STRUCT_FLD(init, innodb_sys_tables_init),
6336 
6337 	/* the function to invoke when plugin is unloaded */
6338 	/* int (*)(void*); */
6339 	STRUCT_FLD(deinit, i_s_common_deinit),
6340 
6341 	/* plugin version (for SHOW PLUGINS) */
6342 	/* unsigned int */
6343 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
6344 
6345 	/* struct st_mysql_show_var* */
6346 	STRUCT_FLD(status_vars, NULL),
6347 
6348 	/* struct st_mysql_sys_var** */
6349 	STRUCT_FLD(system_vars, NULL),
6350 
6351 	/* reserved for dependency checking */
6352 	/* void* */
6353 	STRUCT_FLD(__reserved1, NULL),
6354 
6355 	/* Plugin flags */
6356 	/* unsigned long */
6357 	STRUCT_FLD(flags, 0UL),
6358 };
6359 
6360 /**  SYS_TABLESTATS  ***********************************************/
6361 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLESTATS */
6362 static ST_FIELD_INFO	innodb_sys_tablestats_fields_info[] =
6363 {
6364 #define SYS_TABLESTATS_ID		0
6365 	{STRUCT_FLD(field_name,		"TABLE_ID"),
6366 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6367 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6368 	 STRUCT_FLD(value,		0),
6369 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6370 	 STRUCT_FLD(old_name,		""),
6371 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6372 
6373 #define SYS_TABLESTATS_NAME		1
6374 	{STRUCT_FLD(field_name,		"NAME"),
6375 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
6376 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6377 	 STRUCT_FLD(value,		0),
6378 	 STRUCT_FLD(field_flags,	0),
6379 	 STRUCT_FLD(old_name,		""),
6380 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6381 
6382 #define SYS_TABLESTATS_INIT		2
6383 	{STRUCT_FLD(field_name,		"STATS_INITIALIZED"),
6384 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
6385 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6386 	 STRUCT_FLD(value,		0),
6387 	 STRUCT_FLD(field_flags,	0),
6388 	 STRUCT_FLD(old_name,		""),
6389 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6390 
6391 #define SYS_TABLESTATS_NROW		3
6392 	{STRUCT_FLD(field_name,		"NUM_ROWS"),
6393 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6394 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6395 	 STRUCT_FLD(value,		0),
6396 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6397 	 STRUCT_FLD(old_name,		""),
6398 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6399 
6400 #define SYS_TABLESTATS_CLUST_SIZE	4
6401 	{STRUCT_FLD(field_name,		"CLUST_INDEX_SIZE"),
6402 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6403 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6404 	 STRUCT_FLD(value,		0),
6405 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6406 	 STRUCT_FLD(old_name,		""),
6407 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6408 
6409 #define SYS_TABLESTATS_INDEX_SIZE	5
6410 	{STRUCT_FLD(field_name,		"OTHER_INDEX_SIZE"),
6411 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6412 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6413 	 STRUCT_FLD(value,		0),
6414 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6415 	 STRUCT_FLD(old_name,		""),
6416 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6417 
6418 #define SYS_TABLESTATS_MODIFIED		6
6419 	{STRUCT_FLD(field_name,		"MODIFIED_COUNTER"),
6420 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6421 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6422 	 STRUCT_FLD(value,		0),
6423 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6424 	 STRUCT_FLD(old_name,		""),
6425 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6426 
6427 #define SYS_TABLESTATS_AUTONINC		7
6428 	{STRUCT_FLD(field_name,		"AUTOINC"),
6429 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6430 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6431 	 STRUCT_FLD(value,		0),
6432 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6433 	 STRUCT_FLD(old_name,		""),
6434 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6435 
6436 #define SYS_TABLESTATS_TABLE_REF_COUNT	8
6437 	{STRUCT_FLD(field_name,		"REF_COUNT"),
6438 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6439 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6440 	 STRUCT_FLD(value,		0),
6441 	 STRUCT_FLD(field_flags,	0),
6442 	 STRUCT_FLD(old_name,		""),
6443 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6444 
6445 	END_OF_ST_FIELD_INFO
6446 };
6447 
6448 /**********************************************************************//**
6449 Populate information_schema.innodb_sys_tablestats table with information
6450 from SYS_TABLES.
6451 @return	0 on success */
6452 static
6453 int
i_s_dict_fill_sys_tablestats(THD * thd,dict_table_t * table,TABLE * table_to_fill)6454 i_s_dict_fill_sys_tablestats(
6455 /*=========================*/
6456 	THD*		thd,		/*!< in: thread */
6457 	dict_table_t*	table,		/*!< in: table */
6458 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
6459 {
6460 	Field**		fields;
6461 
6462 	DBUG_ENTER("i_s_dict_fill_sys_tablestats");
6463 
6464 	fields = table_to_fill->field;
6465 
6466 	OK(fields[SYS_TABLESTATS_ID]->store(longlong(table->id), TRUE));
6467 
6468 	OK(field_store_string(fields[SYS_TABLESTATS_NAME], table->name));
6469 
6470 	dict_table_stats_lock(table, RW_S_LATCH);
6471 
6472 	if (table->stat_initialized) {
6473 		OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6474 				      "Initialized"));
6475 
6476 		OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows,
6477 						      TRUE));
6478 
6479 		OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
6480 			static_cast<double>(table->stat_clustered_index_size)));
6481 
6482 		OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
6483 			static_cast<double>(table->stat_sum_of_other_index_sizes)));
6484 
6485 		OK(fields[SYS_TABLESTATS_MODIFIED]->store(
6486 			static_cast<double>(table->stat_modified_counter)));
6487 	} else {
6488 		OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6489 				      "Uninitialized"));
6490 
6491 		OK(fields[SYS_TABLESTATS_NROW]->store(0, TRUE));
6492 
6493 		OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(0));
6494 
6495 		OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(0));
6496 
6497 		OK(fields[SYS_TABLESTATS_MODIFIED]->store(0));
6498 	}
6499 
6500 	dict_table_stats_unlock(table, RW_S_LATCH);
6501 
6502 	OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, TRUE));
6503 
6504 	OK(fields[SYS_TABLESTATS_TABLE_REF_COUNT]->store(
6505 		static_cast<double>(table->n_ref_count)));
6506 
6507 	OK(schema_table_store_record(thd, table_to_fill));
6508 
6509 	DBUG_RETURN(0);
6510 }
6511 
6512 /*******************************************************************//**
6513 Function to go through each record in SYS_TABLES table, and fill the
6514 information_schema.innodb_sys_tablestats table with table statistics
6515 related information
6516 @return 0 on success */
6517 static
6518 int
i_s_sys_tables_fill_table_stats(THD * thd,TABLE_LIST * tables,Item *)6519 i_s_sys_tables_fill_table_stats(
6520 /*============================*/
6521 	THD*		thd,	/*!< in: thread */
6522 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
6523 	Item*		)	/*!< in: condition (not used) */
6524 {
6525 	btr_pcur_t	pcur;
6526 	const rec_t*	rec;
6527 	mem_heap_t*	heap;
6528 	mtr_t		mtr;
6529 
6530 	DBUG_ENTER("i_s_sys_tables_fill_table_stats");
6531 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6532 
6533 	/* deny access to user without PROCESS_ACL privilege */
6534 	if (check_global_access(thd, PROCESS_ACL)) {
6535 		DBUG_RETURN(0);
6536 	}
6537 
6538 	heap = mem_heap_create(1000);
6539 	mutex_enter(&dict_sys->mutex);
6540 	mtr_start(&mtr);
6541 
6542 	rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6543 
6544 	while (rec) {
6545 		const char*	err_msg;
6546 		dict_table_t*	table_rec;
6547 
6548 		/* Fetch the dict_table_t structure corresponding to
6549 		this SYS_TABLES record */
6550 		err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6551 			heap, rec, &table_rec,
6552 			DICT_TABLE_LOAD_FROM_CACHE, &mtr);
6553 
6554 		mutex_exit(&dict_sys->mutex);
6555 
6556 		if (!err_msg) {
6557 			i_s_dict_fill_sys_tablestats(thd, table_rec,
6558 						     tables->table);
6559 		} else {
6560 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
6561 					    ER_CANT_FIND_SYSTEM_REC, "%s",
6562 					    err_msg);
6563 		}
6564 
6565 		mem_heap_empty(heap);
6566 
6567 		/* Get the next record */
6568 		mutex_enter(&dict_sys->mutex);
6569 		mtr_start(&mtr);
6570 		rec = dict_getnext_system(&pcur, &mtr);
6571 	}
6572 
6573 	mtr_commit(&mtr);
6574 	mutex_exit(&dict_sys->mutex);
6575 	mem_heap_free(heap);
6576 
6577 	DBUG_RETURN(0);
6578 }
6579 
6580 /*******************************************************************//**
6581 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tablestats
6582 @return 0 on success */
6583 static
6584 int
innodb_sys_tablestats_init(void * p)6585 innodb_sys_tablestats_init(
6586 /*=======================*/
6587 	void*	p)	/*!< in/out: table schema object */
6588 {
6589 	ST_SCHEMA_TABLE*	schema;
6590 
6591 	DBUG_ENTER("innodb_sys_tablestats_init");
6592 
6593 	schema = (ST_SCHEMA_TABLE*) p;
6594 
6595 	schema->fields_info = innodb_sys_tablestats_fields_info;
6596 	schema->fill_table = i_s_sys_tables_fill_table_stats;
6597 
6598 	DBUG_RETURN(0);
6599 }
6600 
6601 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_tablestats =
6602 {
6603 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
6604 	/* int */
6605 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6606 
6607 	/* pointer to type-specific plugin descriptor */
6608 	/* void* */
6609 	STRUCT_FLD(info, &i_s_info),
6610 
6611 	/* plugin name */
6612 	/* const char* */
6613 	STRUCT_FLD(name, "INNODB_SYS_TABLESTATS"),
6614 
6615 	/* plugin author (for SHOW PLUGINS) */
6616 	/* const char* */
6617 	STRUCT_FLD(author, plugin_author),
6618 
6619 	/* general descriptive text (for SHOW PLUGINS) */
6620 	/* const char* */
6621 	STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
6622 
6623 	/* the plugin license (PLUGIN_LICENSE_XXX) */
6624 	/* int */
6625 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6626 
6627 	/* the function to invoke when plugin is loaded */
6628 	/* int (*)(void*); */
6629 	STRUCT_FLD(init, innodb_sys_tablestats_init),
6630 
6631 	/* the function to invoke when plugin is unloaded */
6632 	/* int (*)(void*); */
6633 	STRUCT_FLD(deinit, i_s_common_deinit),
6634 
6635 	/* plugin version (for SHOW PLUGINS) */
6636 	/* unsigned int */
6637 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
6638 
6639 	/* struct st_mysql_show_var* */
6640 	STRUCT_FLD(status_vars, NULL),
6641 
6642 	/* struct st_mysql_sys_var** */
6643 	STRUCT_FLD(system_vars, NULL),
6644 
6645 	/* reserved for dependency checking */
6646 	/* void* */
6647 	STRUCT_FLD(__reserved1, NULL),
6648 
6649 	/* Plugin flags */
6650 	/* unsigned long */
6651 	STRUCT_FLD(flags, 0UL),
6652 };
6653 
6654 /**  SYS_INDEXES  **************************************************/
6655 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_INDEXES */
6656 static ST_FIELD_INFO	innodb_sysindex_fields_info[] =
6657 {
6658 #define SYS_INDEX_ID		0
6659 	{STRUCT_FLD(field_name,		"INDEX_ID"),
6660 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6661 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6662 	 STRUCT_FLD(value,		0),
6663 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6664 	 STRUCT_FLD(old_name,		""),
6665 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6666 
6667 #define SYS_INDEX_NAME		1
6668 	{STRUCT_FLD(field_name,		"NAME"),
6669 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
6670 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6671 	 STRUCT_FLD(value,		0),
6672 	 STRUCT_FLD(field_flags,	0),
6673 	 STRUCT_FLD(old_name,		""),
6674 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6675 
6676 #define SYS_INDEX_TABLE_ID	2
6677 	{STRUCT_FLD(field_name,		"TABLE_ID"),
6678 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6679 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6680 	 STRUCT_FLD(value,		0),
6681 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6682 	 STRUCT_FLD(old_name,		""),
6683 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6684 
6685 #define SYS_INDEX_TYPE		3
6686 	{STRUCT_FLD(field_name,		"TYPE"),
6687 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6688 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6689 	 STRUCT_FLD(value,		0),
6690 	 STRUCT_FLD(field_flags,	0),
6691 	 STRUCT_FLD(old_name,		""),
6692 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6693 
6694 #define SYS_INDEX_NUM_FIELDS	4
6695 	{STRUCT_FLD(field_name,		"N_FIELDS"),
6696 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6697 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6698 	 STRUCT_FLD(value,		0),
6699 	 STRUCT_FLD(field_flags,	0),
6700 	 STRUCT_FLD(old_name,		""),
6701 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6702 
6703 #define SYS_INDEX_PAGE_NO	5
6704 	{STRUCT_FLD(field_name,		"PAGE_NO"),
6705 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6706 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6707 	 STRUCT_FLD(value,		0),
6708 	 STRUCT_FLD(field_flags,	0),
6709 	 STRUCT_FLD(old_name,		""),
6710 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6711 
6712 #define SYS_INDEX_SPACE		6
6713 	{STRUCT_FLD(field_name,		"SPACE"),
6714 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6715 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6716 	 STRUCT_FLD(value,		0),
6717 	 STRUCT_FLD(field_flags,	0),
6718 	 STRUCT_FLD(old_name,		""),
6719 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6720 
6721 	END_OF_ST_FIELD_INFO
6722 };
6723 
6724 /**********************************************************************//**
6725 Function to populate the information_schema.innodb_sys_indexes table with
6726 collected index information
6727 @return 0 on success */
6728 static
6729 int
i_s_dict_fill_sys_indexes(THD * thd,table_id_t table_id,dict_index_t * index,TABLE * table_to_fill)6730 i_s_dict_fill_sys_indexes(
6731 /*======================*/
6732 	THD*		thd,		/*!< in: thread */
6733 	table_id_t	table_id,	/*!< in: table id */
6734 	dict_index_t*	index,		/*!< in: populated dict_index_t
6735 					struct with index info */
6736 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
6737 {
6738 	Field**		fields;
6739 
6740 	DBUG_ENTER("i_s_dict_fill_sys_indexes");
6741 
6742 	fields = table_to_fill->field;
6743 
6744 	OK(field_store_index_name(fields[SYS_INDEX_NAME], index->name));
6745 
6746 	OK(fields[SYS_INDEX_ID]->store(longlong(index->id), TRUE));
6747 
6748 	OK(fields[SYS_INDEX_TABLE_ID]->store(longlong(table_id), TRUE));
6749 
6750 	OK(fields[SYS_INDEX_TYPE]->store(index->type));
6751 
6752 	OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
6753 
6754 	/* FIL_NULL is ULINT32_UNDEFINED */
6755 	if (index->page == FIL_NULL) {
6756 		OK(fields[SYS_INDEX_PAGE_NO]->store(-1));
6757 	} else {
6758 		OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
6759 	}
6760 
6761 	OK(fields[SYS_INDEX_SPACE]->store(index->space));
6762 
6763 	OK(schema_table_store_record(thd, table_to_fill));
6764 
6765 	DBUG_RETURN(0);
6766 }
6767 /*******************************************************************//**
6768 Function to go through each record in SYS_INDEXES table, and fill the
6769 information_schema.innodb_sys_indexes table with related index information
6770 @return 0 on success */
6771 static
6772 int
i_s_sys_indexes_fill_table(THD * thd,TABLE_LIST * tables,Item *)6773 i_s_sys_indexes_fill_table(
6774 /*=======================*/
6775 	THD*		thd,	/*!< in: thread */
6776 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
6777 	Item*		)	/*!< in: condition (not used) */
6778 {
6779 	btr_pcur_t		pcur;
6780 	const rec_t*		rec;
6781 	mem_heap_t*		heap;
6782 	mtr_t			mtr;
6783 
6784 	DBUG_ENTER("i_s_sys_indexes_fill_table");
6785 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6786 
6787 	/* deny access to user without PROCESS_ACL privilege */
6788 	if (check_global_access(thd, PROCESS_ACL)) {
6789 		DBUG_RETURN(0);
6790 	}
6791 
6792 	heap = mem_heap_create(1000);
6793 	mutex_enter(&dict_sys->mutex);
6794 	mtr_start(&mtr);
6795 
6796 	/* Start scan the SYS_INDEXES table */
6797 	rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
6798 
6799 	/* Process each record in the table */
6800 	while (rec) {
6801 		const char*	err_msg;
6802 		table_id_t	table_id;
6803 		dict_index_t	index_rec;
6804 
6805 		/* Populate a dict_index_t structure with information from
6806 		a SYS_INDEXES row */
6807 		err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
6808 						       &table_id);
6809 
6810 		mtr_commit(&mtr);
6811 		mutex_exit(&dict_sys->mutex);
6812 
6813 		if (!err_msg) {
6814 			i_s_dict_fill_sys_indexes(thd, table_id, &index_rec,
6815 						 tables->table);
6816 		} else {
6817 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
6818 					    ER_CANT_FIND_SYSTEM_REC, "%s",
6819 					    err_msg);
6820 		}
6821 
6822 		mem_heap_empty(heap);
6823 
6824 		/* Get the next record */
6825 		mutex_enter(&dict_sys->mutex);
6826 		mtr_start(&mtr);
6827 		rec = dict_getnext_system(&pcur, &mtr);
6828 	}
6829 
6830 	mtr_commit(&mtr);
6831 	mutex_exit(&dict_sys->mutex);
6832 	mem_heap_free(heap);
6833 
6834 	DBUG_RETURN(0);
6835 }
6836 /*******************************************************************//**
6837 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes
6838 @return 0 on success */
6839 static
6840 int
innodb_sys_indexes_init(void * p)6841 innodb_sys_indexes_init(
6842 /*====================*/
6843 	void*	p)	/*!< in/out: table schema object */
6844 {
6845 	ST_SCHEMA_TABLE*	schema;
6846 
6847 	DBUG_ENTER("innodb_sys_indexes_init");
6848 
6849 	schema = (ST_SCHEMA_TABLE*) p;
6850 
6851 	schema->fields_info = innodb_sysindex_fields_info;
6852 	schema->fill_table = i_s_sys_indexes_fill_table;
6853 
6854 	DBUG_RETURN(0);
6855 }
6856 
6857 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_indexes =
6858 {
6859 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
6860 	/* int */
6861 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6862 
6863 	/* pointer to type-specific plugin descriptor */
6864 	/* void* */
6865 	STRUCT_FLD(info, &i_s_info),
6866 
6867 	/* plugin name */
6868 	/* const char* */
6869 	STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
6870 
6871 	/* plugin author (for SHOW PLUGINS) */
6872 	/* const char* */
6873 	STRUCT_FLD(author, plugin_author),
6874 
6875 	/* general descriptive text (for SHOW PLUGINS) */
6876 	/* const char* */
6877 	STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
6878 
6879 	/* the plugin license (PLUGIN_LICENSE_XXX) */
6880 	/* int */
6881 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6882 
6883 	/* the function to invoke when plugin is loaded */
6884 	/* int (*)(void*); */
6885 	STRUCT_FLD(init, innodb_sys_indexes_init),
6886 
6887 	/* the function to invoke when plugin is unloaded */
6888 	/* int (*)(void*); */
6889 	STRUCT_FLD(deinit, i_s_common_deinit),
6890 
6891 	/* plugin version (for SHOW PLUGINS) */
6892 	/* unsigned int */
6893 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
6894 
6895 	/* struct st_mysql_show_var* */
6896 	STRUCT_FLD(status_vars, NULL),
6897 
6898 	/* struct st_mysql_sys_var** */
6899 	STRUCT_FLD(system_vars, NULL),
6900 
6901 	/* reserved for dependency checking */
6902 	/* void* */
6903 	STRUCT_FLD(__reserved1, NULL),
6904 
6905 	/* Plugin flags */
6906 	/* unsigned long */
6907 	STRUCT_FLD(flags, 0UL),
6908 };
6909 
6910 /**  SYS_COLUMNS  **************************************************/
6911 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_COLUMNS */
6912 static ST_FIELD_INFO	innodb_sys_columns_fields_info[] =
6913 {
6914 #define SYS_COLUMN_TABLE_ID		0
6915 	{STRUCT_FLD(field_name,		"TABLE_ID"),
6916 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6917 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6918 	 STRUCT_FLD(value,		0),
6919 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6920 	 STRUCT_FLD(old_name,		""),
6921 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6922 
6923 #define SYS_COLUMN_NAME		1
6924 	{STRUCT_FLD(field_name,		"NAME"),
6925 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
6926 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6927 	 STRUCT_FLD(value,		0),
6928 	 STRUCT_FLD(field_flags,	0),
6929 	 STRUCT_FLD(old_name,		""),
6930 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6931 
6932 #define SYS_COLUMN_POSITION	2
6933 	{STRUCT_FLD(field_name,		"POS"),
6934 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6935 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6936 	 STRUCT_FLD(value,		0),
6937 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6938 	 STRUCT_FLD(old_name,		""),
6939 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6940 
6941 #define SYS_COLUMN_MTYPE		3
6942 	{STRUCT_FLD(field_name,		"MTYPE"),
6943 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6944 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6945 	 STRUCT_FLD(value,		0),
6946 	 STRUCT_FLD(field_flags,	0),
6947 	 STRUCT_FLD(old_name,		""),
6948 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6949 
6950 #define SYS_COLUMN__PRTYPE	4
6951 	{STRUCT_FLD(field_name,		"PRTYPE"),
6952 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6953 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6954 	 STRUCT_FLD(value,		0),
6955 	 STRUCT_FLD(field_flags,	0),
6956 	 STRUCT_FLD(old_name,		""),
6957 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6958 
6959 #define SYS_COLUMN_COLUMN_LEN	5
6960 	{STRUCT_FLD(field_name,		"LEN"),
6961 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6962 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6963 	 STRUCT_FLD(value,		0),
6964 	 STRUCT_FLD(field_flags,	0),
6965 	 STRUCT_FLD(old_name,		""),
6966 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6967 
6968 	END_OF_ST_FIELD_INFO
6969 };
6970 
6971 /**********************************************************************//**
6972 Function to populate the information_schema.innodb_sys_columns with
6973 related column information
6974 @return 0 on success */
6975 static
6976 int
i_s_dict_fill_sys_columns(THD * thd,table_id_t table_id,const char * col_name,dict_col_t * column,TABLE * table_to_fill)6977 i_s_dict_fill_sys_columns(
6978 /*======================*/
6979 	THD*		thd,		/*!< in: thread */
6980 	table_id_t	table_id,	/*!< in: table ID */
6981 	const char*	col_name,	/*!< in: column name */
6982 	dict_col_t*	column,		/*!< in: dict_col_t struct holding
6983 					more column information */
6984 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
6985 {
6986 	Field**		fields;
6987 
6988 	DBUG_ENTER("i_s_dict_fill_sys_columns");
6989 
6990 	fields = table_to_fill->field;
6991 
6992 	OK(fields[SYS_COLUMN_TABLE_ID]->store(longlong(table_id), TRUE));
6993 
6994 	OK(field_store_string(fields[SYS_COLUMN_NAME], col_name));
6995 
6996 	OK(fields[SYS_COLUMN_POSITION]->store(column->ind));
6997 
6998 	OK(fields[SYS_COLUMN_MTYPE]->store(column->mtype));
6999 
7000 	OK(fields[SYS_COLUMN__PRTYPE]->store(column->prtype));
7001 
7002 	OK(fields[SYS_COLUMN_COLUMN_LEN]->store(column->len));
7003 
7004 	OK(schema_table_store_record(thd, table_to_fill));
7005 
7006 	DBUG_RETURN(0);
7007 }
7008 /*******************************************************************//**
7009 Function to fill information_schema.innodb_sys_columns with information
7010 collected by scanning SYS_COLUMNS table.
7011 @return 0 on success */
7012 static
7013 int
i_s_sys_columns_fill_table(THD * thd,TABLE_LIST * tables,Item *)7014 i_s_sys_columns_fill_table(
7015 /*=======================*/
7016 	THD*		thd,	/*!< in: thread */
7017 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7018 	Item*		)	/*!< in: condition (not used) */
7019 {
7020 	btr_pcur_t	pcur;
7021 	const rec_t*	rec;
7022 	const char*	col_name;
7023 	mem_heap_t*	heap;
7024 	mtr_t		mtr;
7025 
7026 	DBUG_ENTER("i_s_sys_columns_fill_table");
7027 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7028 
7029 	/* deny access to user without PROCESS_ACL privilege */
7030 	if (check_global_access(thd, PROCESS_ACL)) {
7031 		DBUG_RETURN(0);
7032 	}
7033 
7034 	heap = mem_heap_create(1000);
7035 	mutex_enter(&dict_sys->mutex);
7036 	mtr_start(&mtr);
7037 
7038 	rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
7039 
7040 	while (rec) {
7041 		const char*	err_msg;
7042 		dict_col_t	column_rec;
7043 		table_id_t	table_id;
7044 
7045 		/* populate a dict_col_t structure with information from
7046 		a SYS_COLUMNS row */
7047 		err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
7048 						       &table_id, &col_name);
7049 
7050 		mtr_commit(&mtr);
7051 		mutex_exit(&dict_sys->mutex);
7052 
7053 		if (!err_msg) {
7054 			i_s_dict_fill_sys_columns(thd, table_id, col_name,
7055 						 &column_rec,
7056 						 tables->table);
7057 		} else {
7058 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7059 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7060 					    err_msg);
7061 		}
7062 
7063 		mem_heap_empty(heap);
7064 
7065 		/* Get the next record */
7066 		mutex_enter(&dict_sys->mutex);
7067 		mtr_start(&mtr);
7068 		rec = dict_getnext_system(&pcur, &mtr);
7069 	}
7070 
7071 	mtr_commit(&mtr);
7072 	mutex_exit(&dict_sys->mutex);
7073 	mem_heap_free(heap);
7074 
7075 	DBUG_RETURN(0);
7076 }
7077 /*******************************************************************//**
7078 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns
7079 @return 0 on success */
7080 static
7081 int
innodb_sys_columns_init(void * p)7082 innodb_sys_columns_init(
7083 /*====================*/
7084 	void*	p)	/*!< in/out: table schema object */
7085 {
7086 	ST_SCHEMA_TABLE*	schema;
7087 
7088 	DBUG_ENTER("innodb_sys_columns_init");
7089 
7090 	schema = (ST_SCHEMA_TABLE*) p;
7091 
7092 	schema->fields_info = innodb_sys_columns_fields_info;
7093 	schema->fill_table = i_s_sys_columns_fill_table;
7094 
7095 	DBUG_RETURN(0);
7096 }
7097 
7098 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_columns =
7099 {
7100 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7101 	/* int */
7102 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7103 
7104 	/* pointer to type-specific plugin descriptor */
7105 	/* void* */
7106 	STRUCT_FLD(info, &i_s_info),
7107 
7108 	/* plugin name */
7109 	/* const char* */
7110 	STRUCT_FLD(name, "INNODB_SYS_COLUMNS"),
7111 
7112 	/* plugin author (for SHOW PLUGINS) */
7113 	/* const char* */
7114 	STRUCT_FLD(author, plugin_author),
7115 
7116 	/* general descriptive text (for SHOW PLUGINS) */
7117 	/* const char* */
7118 	STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
7119 
7120 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7121 	/* int */
7122 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7123 
7124 	/* the function to invoke when plugin is loaded */
7125 	/* int (*)(void*); */
7126 	STRUCT_FLD(init, innodb_sys_columns_init),
7127 
7128 	/* the function to invoke when plugin is unloaded */
7129 	/* int (*)(void*); */
7130 	STRUCT_FLD(deinit, i_s_common_deinit),
7131 
7132 	/* plugin version (for SHOW PLUGINS) */
7133 	/* unsigned int */
7134 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7135 
7136 	/* struct st_mysql_show_var* */
7137 	STRUCT_FLD(status_vars, NULL),
7138 
7139 	/* struct st_mysql_sys_var** */
7140 	STRUCT_FLD(system_vars, NULL),
7141 
7142 	/* reserved for dependency checking */
7143 	/* void* */
7144 	STRUCT_FLD(__reserved1, NULL),
7145 
7146 	/* Plugin flags */
7147 	/* unsigned long */
7148 	STRUCT_FLD(flags, 0UL),
7149 };
7150 
7151 /**  SYS_FIELDS  ***************************************************/
7152 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FIELDS */
7153 static ST_FIELD_INFO	innodb_sys_fields_fields_info[] =
7154 {
7155 #define SYS_FIELD_INDEX_ID	0
7156 	{STRUCT_FLD(field_name,		"INDEX_ID"),
7157 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
7158 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
7159 	 STRUCT_FLD(value,		0),
7160 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7161 	 STRUCT_FLD(old_name,		""),
7162 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7163 
7164 #define SYS_FIELD_NAME		1
7165 	{STRUCT_FLD(field_name,		"NAME"),
7166 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7167 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7168 	 STRUCT_FLD(value,		0),
7169 	 STRUCT_FLD(field_flags,	0),
7170 	 STRUCT_FLD(old_name,		""),
7171 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7172 
7173 #define SYS_FIELD_POS		2
7174 	{STRUCT_FLD(field_name,		"POS"),
7175 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7176 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7177 	 STRUCT_FLD(value,		0),
7178 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7179 	 STRUCT_FLD(old_name,		""),
7180 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7181 
7182 	END_OF_ST_FIELD_INFO
7183 };
7184 
7185 /**********************************************************************//**
7186 Function to fill information_schema.innodb_sys_fields with information
7187 collected by scanning SYS_FIELDS table.
7188 @return 0 on success */
7189 static
7190 int
i_s_dict_fill_sys_fields(THD * thd,index_id_t index_id,dict_field_t * field,ulint pos,TABLE * table_to_fill)7191 i_s_dict_fill_sys_fields(
7192 /*=====================*/
7193 	THD*		thd,		/*!< in: thread */
7194 	index_id_t	index_id,	/*!< in: index id for the field */
7195 	dict_field_t*	field,		/*!< in: table */
7196 	ulint		pos,		/*!< in: Field position */
7197 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7198 {
7199 	Field**		fields;
7200 
7201 	DBUG_ENTER("i_s_dict_fill_sys_fields");
7202 
7203 	fields = table_to_fill->field;
7204 
7205 	OK(fields[SYS_FIELD_INDEX_ID]->store(longlong(index_id), TRUE));
7206 
7207 	OK(field_store_string(fields[SYS_FIELD_NAME], field->name));
7208 
7209 	OK(fields[SYS_FIELD_POS]->store(static_cast<double>(pos)));
7210 
7211 	OK(schema_table_store_record(thd, table_to_fill));
7212 
7213 	DBUG_RETURN(0);
7214 }
7215 /*******************************************************************//**
7216 Function to go through each record in SYS_FIELDS table, and fill the
7217 information_schema.innodb_sys_fields table with related index field
7218 information
7219 @return 0 on success */
7220 static
7221 int
i_s_sys_fields_fill_table(THD * thd,TABLE_LIST * tables,Item *)7222 i_s_sys_fields_fill_table(
7223 /*======================*/
7224 	THD*		thd,	/*!< in: thread */
7225 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7226 	Item*		)	/*!< in: condition (not used) */
7227 {
7228 	btr_pcur_t	pcur;
7229 	const rec_t*	rec;
7230 	mem_heap_t*	heap;
7231 	index_id_t	last_id;
7232 	mtr_t		mtr;
7233 
7234 	DBUG_ENTER("i_s_sys_fields_fill_table");
7235 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7236 
7237 	/* deny access to user without PROCESS_ACL privilege */
7238 	if (check_global_access(thd, PROCESS_ACL)) {
7239 
7240 		DBUG_RETURN(0);
7241 	}
7242 
7243 	heap = mem_heap_create(1000);
7244 	mutex_enter(&dict_sys->mutex);
7245 	mtr_start(&mtr);
7246 
7247 	/* will save last index id so that we know whether we move to
7248 	the next index. This is used to calculate prefix length */
7249 	last_id = 0;
7250 
7251 	rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
7252 
7253 	while (rec) {
7254 		ulint		pos;
7255 		const char*	err_msg;
7256 		index_id_t	index_id;
7257 		dict_field_t	field_rec;
7258 
7259 		/* Populate a dict_field_t structure with information from
7260 		a SYS_FIELDS row */
7261 		err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
7262 						      &pos, &index_id, last_id);
7263 
7264 		mtr_commit(&mtr);
7265 		mutex_exit(&dict_sys->mutex);
7266 
7267 		if (!err_msg) {
7268 			i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
7269 						 pos, tables->table);
7270 			last_id = index_id;
7271 		} else {
7272 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7273 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7274 					    err_msg);
7275 		}
7276 
7277 		mem_heap_empty(heap);
7278 
7279 		/* Get the next record */
7280 		mutex_enter(&dict_sys->mutex);
7281 		mtr_start(&mtr);
7282 		rec = dict_getnext_system(&pcur, &mtr);
7283 	}
7284 
7285 	mtr_commit(&mtr);
7286 	mutex_exit(&dict_sys->mutex);
7287 	mem_heap_free(heap);
7288 
7289 	DBUG_RETURN(0);
7290 }
7291 /*******************************************************************//**
7292 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields
7293 @return 0 on success */
7294 static
7295 int
innodb_sys_fields_init(void * p)7296 innodb_sys_fields_init(
7297 /*===================*/
7298 	void*   p)	/*!< in/out: table schema object */
7299 {
7300 	ST_SCHEMA_TABLE*	schema;
7301 
7302 	DBUG_ENTER("innodb_sys_field_init");
7303 
7304 	schema = (ST_SCHEMA_TABLE*) p;
7305 
7306 	schema->fields_info = innodb_sys_fields_fields_info;
7307 	schema->fill_table = i_s_sys_fields_fill_table;
7308 
7309 	DBUG_RETURN(0);
7310 }
7311 
7312 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_fields =
7313 {
7314 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7315 	/* int */
7316 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7317 
7318 	/* pointer to type-specific plugin descriptor */
7319 	/* void* */
7320 	STRUCT_FLD(info, &i_s_info),
7321 
7322 	/* plugin name */
7323 	/* const char* */
7324 	STRUCT_FLD(name, "INNODB_SYS_FIELDS"),
7325 
7326 	/* plugin author (for SHOW PLUGINS) */
7327 	/* const char* */
7328 	STRUCT_FLD(author, plugin_author),
7329 
7330 	/* general descriptive text (for SHOW PLUGINS) */
7331 	/* const char* */
7332 	STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
7333 
7334 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7335 	/* int */
7336 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7337 
7338 	/* the function to invoke when plugin is loaded */
7339 	/* int (*)(void*); */
7340 	STRUCT_FLD(init, innodb_sys_fields_init),
7341 
7342 	/* the function to invoke when plugin is unloaded */
7343 	/* int (*)(void*); */
7344 	STRUCT_FLD(deinit, i_s_common_deinit),
7345 
7346 	/* plugin version (for SHOW PLUGINS) */
7347 	/* unsigned int */
7348 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7349 
7350 	/* struct st_mysql_show_var* */
7351 	STRUCT_FLD(status_vars, NULL),
7352 
7353 	/* struct st_mysql_sys_var** */
7354 	STRUCT_FLD(system_vars, NULL),
7355 
7356 	/* reserved for dependency checking */
7357 	/* void* */
7358 	STRUCT_FLD(__reserved1, NULL),
7359 
7360 	/* Plugin flags */
7361 	/* unsigned long */
7362 	STRUCT_FLD(flags, 0UL),
7363 };
7364 
7365 /**  SYS_FOREIGN        ********************************************/
7366 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN */
7367 static ST_FIELD_INFO	innodb_sys_foreign_fields_info[] =
7368 {
7369 #define SYS_FOREIGN_ID		0
7370 	{STRUCT_FLD(field_name,		"ID"),
7371 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7372 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7373 	 STRUCT_FLD(value,		0),
7374 	 STRUCT_FLD(field_flags,	0),
7375 	 STRUCT_FLD(old_name,		""),
7376 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7377 
7378 #define SYS_FOREIGN_FOR_NAME	1
7379 	{STRUCT_FLD(field_name,		"FOR_NAME"),
7380 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7381 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7382 	 STRUCT_FLD(value,		0),
7383 	 STRUCT_FLD(field_flags,	0),
7384 	 STRUCT_FLD(old_name,		""),
7385 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7386 
7387 #define SYS_FOREIGN_REF_NAME	2
7388 	{STRUCT_FLD(field_name,		"REF_NAME"),
7389 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7390 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7391 	 STRUCT_FLD(value,		0),
7392 	 STRUCT_FLD(field_flags,	0),
7393 	 STRUCT_FLD(old_name,		""),
7394 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7395 
7396 #define SYS_FOREIGN_NUM_COL	3
7397 	{STRUCT_FLD(field_name,		"N_COLS"),
7398 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7399 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7400 	 STRUCT_FLD(value,		0),
7401 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7402 	 STRUCT_FLD(old_name,		""),
7403 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7404 
7405 #define SYS_FOREIGN_TYPE	4
7406 	{STRUCT_FLD(field_name,		"TYPE"),
7407 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7408 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7409 	 STRUCT_FLD(value,		0),
7410 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7411 	 STRUCT_FLD(old_name,		""),
7412 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7413 
7414 	END_OF_ST_FIELD_INFO
7415 };
7416 
7417 /**********************************************************************//**
7418 Function to fill information_schema.innodb_sys_foreign with information
7419 collected by scanning SYS_FOREIGN table.
7420 @return 0 on success */
7421 static
7422 int
i_s_dict_fill_sys_foreign(THD * thd,dict_foreign_t * foreign,TABLE * table_to_fill)7423 i_s_dict_fill_sys_foreign(
7424 /*======================*/
7425 	THD*		thd,		/*!< in: thread */
7426 	dict_foreign_t*	foreign,	/*!< in: table */
7427 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7428 {
7429 	Field**		fields;
7430 
7431 	DBUG_ENTER("i_s_dict_fill_sys_foreign");
7432 
7433 	fields = table_to_fill->field;
7434 
7435 	OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
7436 
7437 	OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
7438 			      foreign->foreign_table_name));
7439 
7440 	OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
7441 			      foreign->referenced_table_name));
7442 
7443 	OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
7444 
7445 	OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
7446 
7447 	OK(schema_table_store_record(thd, table_to_fill));
7448 
7449 	DBUG_RETURN(0);
7450 }
7451 
7452 /*******************************************************************//**
7453 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
7454 through each record in SYS_FOREIGN, and extract the foreign key
7455 information.
7456 @return 0 on success */
7457 static
7458 int
i_s_sys_foreign_fill_table(THD * thd,TABLE_LIST * tables,Item *)7459 i_s_sys_foreign_fill_table(
7460 /*=======================*/
7461 	THD*		thd,	/*!< in: thread */
7462 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7463 	Item*		)	/*!< in: condition (not used) */
7464 {
7465 	btr_pcur_t	pcur;
7466 	const rec_t*	rec;
7467 	mem_heap_t*	heap;
7468 	mtr_t		mtr;
7469 
7470 	DBUG_ENTER("i_s_sys_foreign_fill_table");
7471 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7472 
7473 	/* deny access to user without PROCESS_ACL privilege */
7474 	if (check_global_access(thd, PROCESS_ACL)) {
7475 
7476 		DBUG_RETURN(0);
7477 	}
7478 
7479 	heap = mem_heap_create(1000);
7480 	mutex_enter(&dict_sys->mutex);
7481 	mtr_start(&mtr);
7482 
7483 	rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
7484 
7485 	while (rec) {
7486 		const char*	err_msg;
7487 		dict_foreign_t	foreign_rec;
7488 
7489 		/* Populate a dict_foreign_t structure with information from
7490 		a SYS_FOREIGN row */
7491 		err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
7492 
7493 		mtr_commit(&mtr);
7494 		mutex_exit(&dict_sys->mutex);
7495 
7496 		if (!err_msg) {
7497 			i_s_dict_fill_sys_foreign(thd, &foreign_rec,
7498 						 tables->table);
7499 		} else {
7500 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7501 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7502 					    err_msg);
7503 		}
7504 
7505 		mem_heap_empty(heap);
7506 
7507 		/* Get the next record */
7508 		mtr_start(&mtr);
7509 		mutex_enter(&dict_sys->mutex);
7510 		rec = dict_getnext_system(&pcur, &mtr);
7511 	}
7512 
7513 	mtr_commit(&mtr);
7514 	mutex_exit(&dict_sys->mutex);
7515 	mem_heap_free(heap);
7516 
7517 	DBUG_RETURN(0);
7518 }
7519 
7520 /*******************************************************************//**
7521 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
7522 @return 0 on success */
7523 static
7524 int
innodb_sys_foreign_init(void * p)7525 innodb_sys_foreign_init(
7526 /*====================*/
7527 	void*   p)	/*!< in/out: table schema object */
7528 {
7529 	ST_SCHEMA_TABLE*	schema;
7530 
7531 	DBUG_ENTER("innodb_sys_foreign_init");
7532 
7533 	schema = (ST_SCHEMA_TABLE*) p;
7534 
7535 	schema->fields_info = innodb_sys_foreign_fields_info;
7536 	schema->fill_table = i_s_sys_foreign_fill_table;
7537 
7538 	DBUG_RETURN(0);
7539 }
7540 
7541 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_foreign =
7542 {
7543 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7544 	/* int */
7545 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7546 
7547 	/* pointer to type-specific plugin descriptor */
7548 	/* void* */
7549 	STRUCT_FLD(info, &i_s_info),
7550 
7551 	/* plugin name */
7552 	/* const char* */
7553 	STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
7554 
7555 	/* plugin author (for SHOW PLUGINS) */
7556 	/* const char* */
7557 	STRUCT_FLD(author, plugin_author),
7558 
7559 	/* general descriptive text (for SHOW PLUGINS) */
7560 	/* const char* */
7561 	STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
7562 
7563 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7564 	/* int */
7565 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7566 
7567 	/* the function to invoke when plugin is loaded */
7568 	/* int (*)(void*); */
7569 	STRUCT_FLD(init, innodb_sys_foreign_init),
7570 
7571 	/* the function to invoke when plugin is unloaded */
7572 	/* int (*)(void*); */
7573 	STRUCT_FLD(deinit, i_s_common_deinit),
7574 
7575 	/* plugin version (for SHOW PLUGINS) */
7576 	/* unsigned int */
7577 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7578 
7579 	/* struct st_mysql_show_var* */
7580 	STRUCT_FLD(status_vars, NULL),
7581 
7582 	/* struct st_mysql_sys_var** */
7583 	STRUCT_FLD(system_vars, NULL),
7584 
7585 	/* reserved for dependency checking */
7586 	/* void* */
7587 	STRUCT_FLD(__reserved1, NULL),
7588 
7589 	/* Plugin flags */
7590 	/* unsigned long */
7591 	STRUCT_FLD(flags, 0UL),
7592 };
7593 
7594 /**  SYS_FOREIGN_COLS   ********************************************/
7595 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS */
7596 static ST_FIELD_INFO	innodb_sys_foreign_cols_fields_info[] =
7597 {
7598 #define SYS_FOREIGN_COL_ID		0
7599 	{STRUCT_FLD(field_name,		"ID"),
7600 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7601 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7602 	 STRUCT_FLD(value,		0),
7603 	 STRUCT_FLD(field_flags,	0),
7604 	 STRUCT_FLD(old_name,		""),
7605 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7606 
7607 #define SYS_FOREIGN_COL_FOR_NAME	1
7608 	{STRUCT_FLD(field_name,		"FOR_COL_NAME"),
7609 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7610 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7611 	 STRUCT_FLD(value,		0),
7612 	 STRUCT_FLD(field_flags,	0),
7613 	 STRUCT_FLD(old_name,		""),
7614 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7615 
7616 #define SYS_FOREIGN_COL_REF_NAME	2
7617 	{STRUCT_FLD(field_name,		"REF_COL_NAME"),
7618 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7619 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7620 	 STRUCT_FLD(value,		0),
7621 	 STRUCT_FLD(field_flags,	0),
7622 	 STRUCT_FLD(old_name,		""),
7623 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7624 
7625 #define SYS_FOREIGN_COL_POS		3
7626 	{STRUCT_FLD(field_name,		"POS"),
7627 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7628 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7629 	 STRUCT_FLD(value,		0),
7630 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7631 	 STRUCT_FLD(old_name,		""),
7632 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7633 
7634 	END_OF_ST_FIELD_INFO
7635 };
7636 
7637 /**********************************************************************//**
7638 Function to fill information_schema.innodb_sys_foreign_cols with information
7639 collected by scanning SYS_FOREIGN_COLS table.
7640 @return 0 on success */
7641 static
7642 int
i_s_dict_fill_sys_foreign_cols(THD * thd,const char * name,const char * for_col_name,const char * ref_col_name,ulint pos,TABLE * table_to_fill)7643 i_s_dict_fill_sys_foreign_cols(
7644 /*==========================*/
7645 	THD*		thd,		/*!< in: thread */
7646 	const char*	name,		/*!< in: foreign key constraint name */
7647 	const char*	for_col_name,	/*!< in: referencing column name*/
7648 	const char*	ref_col_name,	/*!< in: referenced column
7649 					name */
7650 	ulint		pos,		/*!< in: column position */
7651 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7652 {
7653 	Field**		fields;
7654 
7655 	DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
7656 
7657 	fields = table_to_fill->field;
7658 
7659 	OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
7660 
7661 	OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
7662 
7663 	OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
7664 
7665 	OK(fields[SYS_FOREIGN_COL_POS]->store(static_cast<double>(pos)));
7666 
7667 	OK(schema_table_store_record(thd, table_to_fill));
7668 
7669 	DBUG_RETURN(0);
7670 }
7671 /*******************************************************************//**
7672 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
7673 through each record in SYS_FOREIGN_COLS, and extract the foreign key column
7674 information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
7675 @return 0 on success */
7676 static
7677 int
i_s_sys_foreign_cols_fill_table(THD * thd,TABLE_LIST * tables,Item *)7678 i_s_sys_foreign_cols_fill_table(
7679 /*============================*/
7680 	THD*		thd,	/*!< in: thread */
7681 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7682 	Item*		)	/*!< in: condition (not used) */
7683 {
7684 	btr_pcur_t	pcur;
7685 	const rec_t*	rec;
7686 	mem_heap_t*	heap;
7687 	mtr_t		mtr;
7688 
7689 	DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
7690 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7691 
7692 	/* deny access to user without PROCESS_ACL privilege */
7693 	if (check_global_access(thd, PROCESS_ACL)) {
7694 		DBUG_RETURN(0);
7695 	}
7696 
7697 	heap = mem_heap_create(1000);
7698 	mutex_enter(&dict_sys->mutex);
7699 	mtr_start(&mtr);
7700 
7701 	rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
7702 
7703 	while (rec) {
7704 		const char*	err_msg;
7705 		const char*	name;
7706 		const char*	for_col_name;
7707 		const char*	ref_col_name;
7708 		ulint		pos;
7709 
7710 		/* Extract necessary information from a SYS_FOREIGN_COLS row */
7711 		err_msg = dict_process_sys_foreign_col_rec(
7712 			heap, rec, &name, &for_col_name, &ref_col_name, &pos);
7713 
7714 		mtr_commit(&mtr);
7715 		mutex_exit(&dict_sys->mutex);
7716 
7717 		if (!err_msg) {
7718 			i_s_dict_fill_sys_foreign_cols(
7719 				thd, name, for_col_name, ref_col_name, pos,
7720 				tables->table);
7721 		} else {
7722 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7723 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7724 					    err_msg);
7725 		}
7726 
7727 		mem_heap_empty(heap);
7728 
7729 		/* Get the next record */
7730 		mutex_enter(&dict_sys->mutex);
7731 		mtr_start(&mtr);
7732 		rec = dict_getnext_system(&pcur, &mtr);
7733 	}
7734 
7735 	mtr_commit(&mtr);
7736 	mutex_exit(&dict_sys->mutex);
7737 	mem_heap_free(heap);
7738 
7739 	DBUG_RETURN(0);
7740 }
7741 /*******************************************************************//**
7742 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
7743 @return 0 on success */
7744 static
7745 int
innodb_sys_foreign_cols_init(void * p)7746 innodb_sys_foreign_cols_init(
7747 /*========================*/
7748 	void*	p)	/*!< in/out: table schema object */
7749 {
7750 	ST_SCHEMA_TABLE*	schema;
7751 
7752 	DBUG_ENTER("innodb_sys_foreign_cols_init");
7753 
7754 	schema = (ST_SCHEMA_TABLE*) p;
7755 
7756 	schema->fields_info = innodb_sys_foreign_cols_fields_info;
7757 	schema->fill_table = i_s_sys_foreign_cols_fill_table;
7758 
7759 	DBUG_RETURN(0);
7760 }
7761 
7762 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_foreign_cols =
7763 {
7764 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7765 	/* int */
7766 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7767 
7768 	/* pointer to type-specific plugin descriptor */
7769 	/* void* */
7770 	STRUCT_FLD(info, &i_s_info),
7771 
7772 	/* plugin name */
7773 	/* const char* */
7774 	STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
7775 
7776 	/* plugin author (for SHOW PLUGINS) */
7777 	/* const char* */
7778 	STRUCT_FLD(author, plugin_author),
7779 
7780 	/* general descriptive text (for SHOW PLUGINS) */
7781 	/* const char* */
7782 	STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
7783 
7784 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7785 	/* int */
7786 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7787 
7788 	/* the function to invoke when plugin is loaded */
7789 	/* int (*)(void*); */
7790 	STRUCT_FLD(init, innodb_sys_foreign_cols_init),
7791 
7792 	/* the function to invoke when plugin is unloaded */
7793 	/* int (*)(void*); */
7794 	STRUCT_FLD(deinit, i_s_common_deinit),
7795 
7796 	/* plugin version (for SHOW PLUGINS) */
7797 	/* unsigned int */
7798 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7799 
7800 	/* struct st_mysql_show_var* */
7801 	STRUCT_FLD(status_vars, NULL),
7802 
7803 	/* struct st_mysql_sys_var** */
7804 	STRUCT_FLD(system_vars, NULL),
7805 
7806 	/* reserved for dependency checking */
7807 	/* void* */
7808 	STRUCT_FLD(__reserved1, NULL),
7809 
7810 	/* Plugin flags */
7811 	/* unsigned long */
7812 	STRUCT_FLD(flags, 0UL),
7813 };
7814 
7815 /**  SYS_TABLESPACES    ********************************************/
7816 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES */
7817 static ST_FIELD_INFO	innodb_sys_tablespaces_fields_info[] =
7818 {
7819 #define SYS_TABLESPACES_SPACE		0
7820 	{STRUCT_FLD(field_name,		"SPACE"),
7821 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7822 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7823 	 STRUCT_FLD(value,		0),
7824 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7825 	 STRUCT_FLD(old_name,		""),
7826 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7827 
7828 #define SYS_TABLESPACES_NAME		1
7829 	{STRUCT_FLD(field_name,		"NAME"),
7830 	 STRUCT_FLD(field_length,	MAX_FULL_NAME_LEN + 1),
7831 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7832 	 STRUCT_FLD(value,		0),
7833 	 STRUCT_FLD(field_flags,	0),
7834 	 STRUCT_FLD(old_name,		""),
7835 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7836 
7837 #define SYS_TABLESPACES_FLAGS		2
7838 	{STRUCT_FLD(field_name,		"FLAG"),
7839 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7840 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7841 	 STRUCT_FLD(value,		0),
7842 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7843 	 STRUCT_FLD(old_name,		""),
7844 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7845 
7846 #define SYS_TABLESPACES_FILE_FORMAT	3
7847 	{STRUCT_FLD(field_name,		"FILE_FORMAT"),
7848 	 STRUCT_FLD(field_length,	10),
7849 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7850 	 STRUCT_FLD(value,		0),
7851 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
7852 	 STRUCT_FLD(old_name,		""),
7853 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7854 
7855 #define SYS_TABLESPACES_ROW_FORMAT	4
7856 	{STRUCT_FLD(field_name,		"ROW_FORMAT"),
7857 	 STRUCT_FLD(field_length,	22),
7858 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7859 	 STRUCT_FLD(value,		0),
7860 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
7861 	 STRUCT_FLD(old_name,		""),
7862 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7863 
7864 #define SYS_TABLESPACES_PAGE_SIZE	5
7865 	{STRUCT_FLD(field_name,		"PAGE_SIZE"),
7866 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7867 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7868 	 STRUCT_FLD(value,		0),
7869 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7870 	 STRUCT_FLD(old_name,		""),
7871 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7872 
7873 #define SYS_TABLESPACES_ZIP_PAGE_SIZE	6
7874 	{STRUCT_FLD(field_name,		"ZIP_PAGE_SIZE"),
7875 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7876 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7877 	 STRUCT_FLD(value,		0),
7878 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7879 	 STRUCT_FLD(old_name,		""),
7880 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7881 
7882 	END_OF_ST_FIELD_INFO
7883 
7884 };
7885 
7886 /**********************************************************************//**
7887 Function to fill INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES with information
7888 collected by scanning SYS_TABLESPACESS table.
7889 @return 0 on success */
7890 static
7891 int
i_s_dict_fill_sys_tablespaces(THD * thd,ulint space,const char * name,ulint flags,TABLE * table_to_fill)7892 i_s_dict_fill_sys_tablespaces(
7893 /*==========================*/
7894 	THD*		thd,		/*!< in: thread */
7895 	ulint		space,		/*!< in: space ID */
7896 	const char*	name,		/*!< in: tablespace name */
7897 	ulint		flags,		/*!< in: tablespace flags */
7898 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7899 {
7900 	Field**	fields;
7901 	ulint	atomic_blobs	= FSP_FLAGS_HAS_ATOMIC_BLOBS(flags);
7902 	ulint	page_size	= fsp_flags_get_page_size(flags);;
7903 	ulint	zip_size	= fsp_flags_get_zip_size(flags);
7904 	const char* file_format;
7905 	const char* row_format;
7906 
7907 	DBUG_ENTER("i_s_dict_fill_sys_tablespaces");
7908 
7909 	file_format = trx_sys_file_format_id_to_name(atomic_blobs);
7910 	if (!atomic_blobs) {
7911 		row_format = "Compact or Redundant";
7912 	} else if DICT_TF_GET_ZIP_SSIZE(flags) {
7913 		row_format = "Compressed";
7914 	} else {
7915 		row_format = "Dynamic";
7916 	}
7917 
7918 	fields = table_to_fill->field;
7919 
7920 	OK(fields[SYS_TABLESPACES_SPACE]->store(
7921 		static_cast<double>(space)));
7922 
7923 	OK(field_store_string(fields[SYS_TABLESPACES_NAME], name));
7924 
7925 	OK(fields[SYS_TABLESPACES_FLAGS]->store(
7926 		static_cast<double>(flags)));
7927 
7928 	OK(field_store_string(fields[SYS_TABLESPACES_FILE_FORMAT],
7929 			      file_format));
7930 
7931 	OK(field_store_string(fields[SYS_TABLESPACES_ROW_FORMAT],
7932 			      row_format));
7933 
7934 	OK(fields[SYS_TABLESPACES_PAGE_SIZE]->store(
7935 		static_cast<double>(page_size)));
7936 
7937 	OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store(
7938 		static_cast<double>(zip_size)));
7939 
7940 	OK(schema_table_store_record(thd, table_to_fill));
7941 
7942 	DBUG_RETURN(0);
7943 }
7944 /*******************************************************************//**
7945 Function to populate INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
7946 Loop through each record in SYS_TABLESPACES, and extract the column
7947 information and fill the INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
7948 @return 0 on success */
7949 static
7950 int
i_s_sys_tablespaces_fill_table(THD * thd,TABLE_LIST * tables,Item *)7951 i_s_sys_tablespaces_fill_table(
7952 /*===========================*/
7953 	THD*		thd,	/*!< in: thread */
7954 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7955 	Item*		)	/*!< in: condition (not used) */
7956 {
7957 	btr_pcur_t	pcur;
7958 	const rec_t*	rec;
7959 	mem_heap_t*	heap;
7960 	mtr_t		mtr;
7961 
7962 	DBUG_ENTER("i_s_sys_tablespaces_fill_table");
7963 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7964 
7965 	/* deny access to user without PROCESS_ACL privilege */
7966 	if (check_global_access(thd, PROCESS_ACL)) {
7967 		DBUG_RETURN(0);
7968 	}
7969 
7970 	heap = mem_heap_create(1000);
7971 	mutex_enter(&dict_sys->mutex);
7972 	mtr_start(&mtr);
7973 
7974 	rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
7975 
7976 	while (rec) {
7977 		const char*	err_msg;
7978 		ulint		space;
7979 		const char*	name;
7980 		ulint		flags;
7981 
7982 		/* Extract necessary information from a SYS_TABLESPACES row */
7983 		err_msg = dict_process_sys_tablespaces(
7984 			heap, rec, &space, &name, &flags);
7985 
7986 		mtr_commit(&mtr);
7987 		mutex_exit(&dict_sys->mutex);
7988 
7989 		if (!err_msg) {
7990 			i_s_dict_fill_sys_tablespaces(
7991 				thd, space, name, flags,
7992 				tables->table);
7993 		} else {
7994 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
7995 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7996 					    err_msg);
7997 		}
7998 
7999 		mem_heap_empty(heap);
8000 
8001 		/* Get the next record */
8002 		mutex_enter(&dict_sys->mutex);
8003 		mtr_start(&mtr);
8004 		rec = dict_getnext_system(&pcur, &mtr);
8005 	}
8006 
8007 	mtr_commit(&mtr);
8008 	mutex_exit(&dict_sys->mutex);
8009 	mem_heap_free(heap);
8010 
8011 	DBUG_RETURN(0);
8012 }
8013 /*******************************************************************//**
8014 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
8015 @return 0 on success */
8016 static
8017 int
innodb_sys_tablespaces_init(void * p)8018 innodb_sys_tablespaces_init(
8019 /*========================*/
8020 	void*	p)	/*!< in/out: table schema object */
8021 {
8022 	ST_SCHEMA_TABLE*	schema;
8023 
8024 	DBUG_ENTER("innodb_sys_tablespaces_init");
8025 
8026 	schema = (ST_SCHEMA_TABLE*) p;
8027 
8028 	schema->fields_info = innodb_sys_tablespaces_fields_info;
8029 	schema->fill_table = i_s_sys_tablespaces_fill_table;
8030 
8031 	DBUG_RETURN(0);
8032 }
8033 
8034 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_tablespaces =
8035 {
8036 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
8037 	/* int */
8038 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8039 
8040 	/* pointer to type-specific plugin descriptor */
8041 	/* void* */
8042 	STRUCT_FLD(info, &i_s_info),
8043 
8044 	/* plugin name */
8045 	/* const char* */
8046 	STRUCT_FLD(name, "INNODB_SYS_TABLESPACES"),
8047 
8048 	/* plugin author (for SHOW PLUGINS) */
8049 	/* const char* */
8050 	STRUCT_FLD(author, plugin_author),
8051 
8052 	/* general descriptive text (for SHOW PLUGINS) */
8053 	/* const char* */
8054 	STRUCT_FLD(descr, "InnoDB SYS_TABLESPACES"),
8055 
8056 	/* the plugin license (PLUGIN_LICENSE_XXX) */
8057 	/* int */
8058 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8059 
8060 	/* the function to invoke when plugin is loaded */
8061 	/* int (*)(void*); */
8062 	STRUCT_FLD(init, innodb_sys_tablespaces_init),
8063 
8064 	/* the function to invoke when plugin is unloaded */
8065 	/* int (*)(void*); */
8066 	STRUCT_FLD(deinit, i_s_common_deinit),
8067 
8068 	/* plugin version (for SHOW PLUGINS) */
8069 	/* unsigned int */
8070 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
8071 
8072 	/* struct st_mysql_show_var* */
8073 	STRUCT_FLD(status_vars, NULL),
8074 
8075 	/* struct st_mysql_sys_var** */
8076 	STRUCT_FLD(system_vars, NULL),
8077 
8078 	/* reserved for dependency checking */
8079 	/* void* */
8080 	STRUCT_FLD(__reserved1, NULL),
8081 
8082 	/* Plugin flags */
8083 	/* unsigned long */
8084 	STRUCT_FLD(flags, 0UL),
8085 };
8086 
8087 /**  SYS_DATAFILES  ************************************************/
8088 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES */
8089 static ST_FIELD_INFO	innodb_sys_datafiles_fields_info[] =
8090 {
8091 #define SYS_DATAFILES_SPACE		0
8092 	{STRUCT_FLD(field_name,		"SPACE"),
8093 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8094 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8095 	 STRUCT_FLD(value,		0),
8096 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8097 	 STRUCT_FLD(old_name,		""),
8098 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8099 
8100 #define SYS_DATAFILES_PATH		1
8101 	{STRUCT_FLD(field_name,		"PATH"),
8102 	 STRUCT_FLD(field_length,	OS_FILE_MAX_PATH),
8103 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8104 	 STRUCT_FLD(value,		0),
8105 	 STRUCT_FLD(field_flags,	0),
8106 	 STRUCT_FLD(old_name,		""),
8107 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8108 
8109 	END_OF_ST_FIELD_INFO
8110 };
8111 
8112 /**********************************************************************//**
8113 Function to fill INFORMATION_SCHEMA.INNODB_SYS_DATAFILES with information
8114 collected by scanning SYS_DATAFILESS table.
8115 @return 0 on success */
8116 static
8117 int
i_s_dict_fill_sys_datafiles(THD * thd,ulint space,const char * path,TABLE * table_to_fill)8118 i_s_dict_fill_sys_datafiles(
8119 /*========================*/
8120 	THD*		thd,		/*!< in: thread */
8121 	ulint		space,		/*!< in: space ID */
8122 	const char*	path,		/*!< in: absolute path */
8123 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
8124 {
8125 	Field**		fields;
8126 
8127 	DBUG_ENTER("i_s_dict_fill_sys_datafiles");
8128 
8129 	fields = table_to_fill->field;
8130 
8131 	OK(field_store_ulint(fields[SYS_DATAFILES_SPACE], space));
8132 
8133 	OK(field_store_string(fields[SYS_DATAFILES_PATH], path));
8134 
8135 	OK(schema_table_store_record(thd, table_to_fill));
8136 
8137 	DBUG_RETURN(0);
8138 }
8139 /*******************************************************************//**
8140 Function to populate INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8141 Loop through each record in SYS_DATAFILES, and extract the column
8142 information and fill the INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8143 @return 0 on success */
8144 static
8145 int
i_s_sys_datafiles_fill_table(THD * thd,TABLE_LIST * tables,Item *)8146 i_s_sys_datafiles_fill_table(
8147 /*=========================*/
8148 	THD*		thd,	/*!< in: thread */
8149 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
8150 	Item*		)	/*!< in: condition (not used) */
8151 {
8152 	btr_pcur_t	pcur;
8153 	const rec_t*	rec;
8154 	mem_heap_t*	heap;
8155 	mtr_t		mtr;
8156 
8157 	DBUG_ENTER("i_s_sys_datafiles_fill_table");
8158 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8159 
8160 	/* deny access to user without PROCESS_ACL privilege */
8161 	if (check_global_access(thd, PROCESS_ACL)) {
8162 		DBUG_RETURN(0);
8163 	}
8164 
8165 	heap = mem_heap_create(1000);
8166 	mutex_enter(&dict_sys->mutex);
8167 	mtr_start(&mtr);
8168 
8169 	rec = dict_startscan_system(&pcur, &mtr, SYS_DATAFILES);
8170 
8171 	while (rec) {
8172 		const char*	err_msg;
8173 		ulint		space;
8174 		const char*	path;
8175 
8176 		/* Extract necessary information from a SYS_DATAFILES row */
8177 		err_msg = dict_process_sys_datafiles(
8178 			heap, rec, &space, &path);
8179 
8180 		mtr_commit(&mtr);
8181 		mutex_exit(&dict_sys->mutex);
8182 
8183 		if (!err_msg) {
8184 			i_s_dict_fill_sys_datafiles(
8185 				thd, space, path, tables->table);
8186 		} else {
8187 			push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
8188 					    ER_CANT_FIND_SYSTEM_REC, "%s",
8189 					    err_msg);
8190 		}
8191 
8192 		mem_heap_empty(heap);
8193 
8194 		/* Get the next record */
8195 		mutex_enter(&dict_sys->mutex);
8196 		mtr_start(&mtr);
8197 		rec = dict_getnext_system(&pcur, &mtr);
8198 	}
8199 
8200 	mtr_commit(&mtr);
8201 	mutex_exit(&dict_sys->mutex);
8202 	mem_heap_free(heap);
8203 
8204 	DBUG_RETURN(0);
8205 }
8206 /*******************************************************************//**
8207 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES
8208 @return 0 on success */
8209 static
8210 int
innodb_sys_datafiles_init(void * p)8211 innodb_sys_datafiles_init(
8212 /*======================*/
8213 	void*	p)	/*!< in/out: table schema object */
8214 {
8215 	ST_SCHEMA_TABLE*	schema;
8216 
8217 	DBUG_ENTER("innodb_sys_datafiles_init");
8218 
8219 	schema = (ST_SCHEMA_TABLE*) p;
8220 
8221 	schema->fields_info = innodb_sys_datafiles_fields_info;
8222 	schema->fill_table = i_s_sys_datafiles_fill_table;
8223 
8224 	DBUG_RETURN(0);
8225 }
8226 
8227 UNIV_INTERN struct st_mysql_plugin	i_s_innodb_sys_datafiles =
8228 {
8229 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
8230 	/* int */
8231 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8232 
8233 	/* pointer to type-specific plugin descriptor */
8234 	/* void* */
8235 	STRUCT_FLD(info, &i_s_info),
8236 
8237 	/* plugin name */
8238 	/* const char* */
8239 	STRUCT_FLD(name, "INNODB_SYS_DATAFILES"),
8240 
8241 	/* plugin author (for SHOW PLUGINS) */
8242 	/* const char* */
8243 	STRUCT_FLD(author, plugin_author),
8244 
8245 	/* general descriptive text (for SHOW PLUGINS) */
8246 	/* const char* */
8247 	STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
8248 
8249 	/* the plugin license (PLUGIN_LICENSE_XXX) */
8250 	/* int */
8251 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8252 
8253 	/* the function to invoke when plugin is loaded */
8254 	/* int (*)(void*); */
8255 	STRUCT_FLD(init, innodb_sys_datafiles_init),
8256 
8257 	/* the function to invoke when plugin is unloaded */
8258 	/* int (*)(void*); */
8259 	STRUCT_FLD(deinit, i_s_common_deinit),
8260 
8261 	/* plugin version (for SHOW PLUGINS) */
8262 	/* unsigned int */
8263 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
8264 
8265 	/* struct st_mysql_show_var* */
8266 	STRUCT_FLD(status_vars, NULL),
8267 
8268 	/* struct st_mysql_sys_var** */
8269 	STRUCT_FLD(system_vars, NULL),
8270 
8271 	/* reserved for dependency checking */
8272 	/* void* */
8273 	STRUCT_FLD(__reserved1, NULL),
8274 
8275 	/* Plugin flags */
8276 	/* unsigned long */
8277 	STRUCT_FLD(flags, 0UL),
8278 };
8279