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