1 /*****************************************************************************
2 
3 Copyright (c) 2007, 2021, Oracle and/or its affiliates.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License, version 2.0,
7 as published by the Free Software Foundation.
8 
9 This program is also distributed with certain software (including
10 but not limited to OpenSSL) that is licensed under separate terms,
11 as designated in a particular file or component or in included license
12 documentation.  The authors of MySQL hereby grant you an additional
13 permission to link the program and your derivative works with the
14 separately licensed software that they have included with MySQL.
15 
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License, version 2.0, for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24 
25 *****************************************************************************/
26 
27 /**************************************************//**
28 @file handler/i_s.cc
29 InnoDB INFORMATION SCHEMA tables interface to MySQL.
30 
31 Created July 18, 2007 Vasil Dimov
32 *******************************************************/
33 
34 #include "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 	/* Check if cache is being synced.
3476 	Note: we wait till cache is being synced. */
3477 	while (cache->sync->in_progress) {
3478 		os_event_wait(cache->sync->event);
3479 	}
3480 
3481 	for (ulint i = 0; i < ib_vector_size(cache->indexes); i++) {
3482 		fts_index_cache_t*      index_cache;
3483 
3484 		index_cache = static_cast<fts_index_cache_t*> (
3485 			ib_vector_get(cache->indexes, i));
3486 
3487 		i_s_fts_index_cache_fill_one_index(index_cache, thd, tables);
3488 	}
3489 
3490 	dict_table_close(user_table, FALSE, FALSE);
3491 
3492 	DBUG_RETURN(0);
3493 }
3494 
3495 /*******************************************************************//**
3496 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
3497 @return 0 on success */
3498 static
3499 int
i_s_fts_index_cache_init(void * p)3500 i_s_fts_index_cache_init(
3501 /*=====================*/
3502 	void*	p)	/*!< in/out: table schema object */
3503 {
3504 	DBUG_ENTER("i_s_fts_index_cache_init");
3505 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3506 
3507 	schema->fields_info = i_s_fts_index_fields_info;
3508 	schema->fill_table = i_s_fts_index_cache_fill;
3509 
3510 	DBUG_RETURN(0);
3511 }
3512 
3513 struct st_mysql_plugin	i_s_innodb_ft_index_cache =
3514 {
3515 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3516 	/* int */
3517 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3518 
3519 	/* pointer to type-specific plugin descriptor */
3520 	/* void* */
3521 	STRUCT_FLD(info, &i_s_info),
3522 
3523 	/* plugin name */
3524 	/* const char* */
3525 	STRUCT_FLD(name, "INNODB_FT_INDEX_CACHE"),
3526 
3527 	/* plugin author (for SHOW PLUGINS) */
3528 	/* const char* */
3529 	STRUCT_FLD(author, plugin_author),
3530 
3531 	/* general descriptive text (for SHOW PLUGINS) */
3532 	/* const char* */
3533 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX CACHED"),
3534 
3535 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3536 	/* int */
3537 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3538 
3539 	/* the function to invoke when plugin is loaded */
3540 	/* int (*)(void*); */
3541 	STRUCT_FLD(init, i_s_fts_index_cache_init),
3542 
3543 	/* the function to invoke when plugin is unloaded */
3544 	/* int (*)(void*); */
3545 	STRUCT_FLD(deinit, i_s_common_deinit),
3546 
3547 	/* plugin version (for SHOW PLUGINS) */
3548 	/* unsigned int */
3549 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
3550 
3551 	/* struct st_mysql_show_var* */
3552 	STRUCT_FLD(status_vars, NULL),
3553 
3554 	/* struct st_mysql_sys_var** */
3555 	STRUCT_FLD(system_vars, NULL),
3556 
3557 	/* reserved for dependency checking */
3558 	/* void* */
3559 	STRUCT_FLD(__reserved1, NULL),
3560 
3561 	/* Plugin flags */
3562 	/* unsigned long */
3563 	STRUCT_FLD(flags, 0UL),
3564 };
3565 
3566 /*******************************************************************//**
3567 Go through a FTS index auxiliary table, fetch its rows and fill
3568 FTS word cache structure.
3569 @return DB_SUCCESS on success, otherwise error code */
3570 static
3571 dberr_t
i_s_fts_index_table_fill_selected(dict_index_t * index,ib_vector_t * words,ulint selected,fts_string_t * word)3572 i_s_fts_index_table_fill_selected(
3573 /*==============================*/
3574 	dict_index_t*		index,		/*!< in: FTS index */
3575 	ib_vector_t*		words,		/*!< in/out: vector to hold
3576 						fetched words */
3577 	ulint			selected,	/*!< in: selected FTS index */
3578 	fts_string_t*		word)		/*!< in: word to select */
3579 {
3580 	pars_info_t*		info;
3581 	fts_table_t		fts_table;
3582 	trx_t*			trx;
3583 	que_t*			graph;
3584 	dberr_t			error;
3585 	fts_fetch_t		fetch;
3586 	char			table_name[MAX_FULL_NAME_LEN];
3587 
3588 	info = pars_info_create();
3589 
3590 	fetch.read_arg = words;
3591 	fetch.read_record = fts_optimize_index_fetch_node;
3592 	fetch.total_memory = 0;
3593 
3594 	DBUG_EXECUTE_IF("fts_instrument_result_cache_limit",
3595 	        fts_result_cache_limit = 8192;
3596 	);
3597 
3598 	trx = trx_allocate_for_background();
3599 
3600 	trx->op_info = "fetching FTS index nodes";
3601 
3602 	pars_info_bind_function(info, "my_func", fetch.read_record, &fetch);
3603 	pars_info_bind_varchar_literal(info, "word", word->f_str, word->f_len);
3604 
3605 	FTS_INIT_INDEX_TABLE(&fts_table, fts_get_suffix(selected),
3606 			     FTS_INDEX_TABLE, index);
3607 	fts_get_table_name(&fts_table, table_name);
3608 	pars_info_bind_id(info, true, "table_name", table_name);
3609 
3610 	graph = fts_parse_sql(
3611 		&fts_table, info,
3612 		"DECLARE FUNCTION my_func;\n"
3613 		"DECLARE CURSOR c IS"
3614 		" SELECT word, doc_count, first_doc_id, last_doc_id,"
3615 		" ilist\n"
3616 		" FROM $table_name WHERE word >= :word;\n"
3617 		"BEGIN\n"
3618 		"\n"
3619 		"OPEN c;\n"
3620 		"WHILE 1 = 1 LOOP\n"
3621 		"  FETCH c INTO my_func();\n"
3622 		"  IF c % NOTFOUND THEN\n"
3623 		"    EXIT;\n"
3624 		"  END IF;\n"
3625 		"END LOOP;\n"
3626 		"CLOSE c;");
3627 
3628 	for (;;) {
3629 		error = fts_eval_sql(trx, graph);
3630 
3631 		if (error == DB_SUCCESS) {
3632 			fts_sql_commit(trx);
3633 
3634 			break;
3635 		} else {
3636 			fts_sql_rollback(trx);
3637 
3638 			if (error == DB_LOCK_WAIT_TIMEOUT) {
3639 				ib::warn() << "Lock wait timeout reading"
3640 					" FTS index. Retrying!";
3641 
3642 				trx->error_state = DB_SUCCESS;
3643 			} else {
3644 				ib::error() << "Error occurred while reading"
3645 					" FTS index: " << ut_strerr(error);
3646 				break;
3647 			}
3648 		}
3649 	}
3650 
3651 	mutex_enter(&dict_sys->mutex);
3652 	que_graph_free(graph);
3653 	mutex_exit(&dict_sys->mutex);
3654 
3655 	trx_free_for_background(trx);
3656 
3657 	if (fetch.total_memory >= fts_result_cache_limit) {
3658 		error = DB_FTS_EXCEED_RESULT_CACHE_LIMIT;
3659 	}
3660 
3661 	return(error);
3662 }
3663 
3664 /*******************************************************************//**
3665 Free words. */
3666 static
3667 void
i_s_fts_index_table_free_one_fetch(ib_vector_t * words)3668 i_s_fts_index_table_free_one_fetch(
3669 /*===============================*/
3670 	ib_vector_t*		words)		/*!< in: words fetched */
3671 {
3672 	for (ulint i = 0; i < ib_vector_size(words); i++) {
3673 		fts_word_t*	word;
3674 
3675 		word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3676 
3677 		for (ulint j = 0; j < ib_vector_size(word->nodes); j++) {
3678 			fts_node_t*     node;
3679 
3680 			node = static_cast<fts_node_t*> (ib_vector_get(
3681 				word->nodes, j));
3682 			ut_free(node->ilist);
3683 		}
3684 
3685 		fts_word_free(word);
3686 	}
3687 
3688 	ib_vector_reset(words);
3689 }
3690 
3691 /*******************************************************************//**
3692 Go through words, fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3693 @return	0 on success, 1 on failure */
3694 static
3695 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)3696 i_s_fts_index_table_fill_one_fetch(
3697 /*===============================*/
3698 	CHARSET_INFO*		index_charset,	/*!< in: FTS index charset */
3699 	THD*			thd,		/*!< in: thread */
3700 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
3701 	ib_vector_t*		words,		/*!< in: words fetched */
3702 	fts_string_t*		conv_str,	/*!< in: string for conversion*/
3703 	bool			has_more)	/*!< in: has more to fetch */
3704 {
3705 	TABLE*			table = (TABLE*) tables->table;
3706 	Field**			fields;
3707 	uint			dummy_errors;
3708 	char*			word_str;
3709 	ulint			words_size;
3710 	int			ret = 0;
3711 
3712 	DBUG_ENTER("i_s_fts_index_table_fill_one_fetch");
3713 
3714 	fields = table->field;
3715 
3716 	words_size = ib_vector_size(words);
3717 	if (has_more) {
3718 		/* the last word is not fetched completely. */
3719 		ut_ad(words_size > 1);
3720 		words_size -= 1;
3721 	}
3722 
3723 	/* Go through each word in the index cache */
3724 	for (ulint i = 0; i < words_size; i++) {
3725 		fts_word_t*	word;
3726 
3727 		word = static_cast<fts_word_t*>(ib_vector_get(words, i));
3728 
3729 		word->text.f_str[word->text.f_len] = 0;
3730 
3731 		/* Convert word from index charset to system_charset_info */
3732 		if (index_charset->cset != system_charset_info->cset) {
3733 			conv_str->f_n_char = my_convert(
3734 				reinterpret_cast<char*>(conv_str->f_str),
3735 				static_cast<uint32>(conv_str->f_len),
3736 				system_charset_info,
3737 				reinterpret_cast<char*>(word->text.f_str),
3738 				static_cast<uint32>(word->text.f_len),
3739 				index_charset, &dummy_errors);
3740 			ut_ad(conv_str->f_n_char <= conv_str->f_len);
3741 			conv_str->f_str[conv_str->f_n_char] = 0;
3742 			word_str = reinterpret_cast<char*>(conv_str->f_str);
3743 		} else {
3744 			word_str = reinterpret_cast<char*>(word->text.f_str);
3745 		}
3746 
3747 		/* Decrypt the ilist, and display Dod ID and word position */
3748 		for (ulint i = 0; i < ib_vector_size(word->nodes); i++) {
3749 			fts_node_t*	node;
3750 			byte*		ptr;
3751 			ulint		decoded = 0;
3752 			doc_id_t	doc_id = 0;
3753 
3754 			node = static_cast<fts_node_t*> (ib_vector_get(
3755 				word->nodes, i));
3756 
3757 			ptr = node->ilist;
3758 
3759 			while (decoded < node->ilist_size) {
3760 				ulint	pos = fts_decode_vlc(&ptr);
3761 
3762 				doc_id += pos;
3763 
3764 				/* Get position info */
3765 				while (*ptr) {
3766 					pos = fts_decode_vlc(&ptr);
3767 
3768 					OK(field_store_string(
3769 						   fields[I_S_FTS_WORD],
3770 						   word_str));
3771 
3772 					OK(fields[I_S_FTS_FIRST_DOC_ID]->store(
3773 						   node->first_doc_id, true));
3774 
3775 					OK(fields[I_S_FTS_LAST_DOC_ID]->store(
3776 						   node->last_doc_id, true));
3777 
3778 					OK(fields[I_S_FTS_DOC_COUNT]->store(
3779 						   node->doc_count, true));
3780 
3781 					OK(fields[I_S_FTS_ILIST_DOC_ID]->store(
3782 						   doc_id, true));
3783 
3784 					OK(fields[I_S_FTS_ILIST_DOC_POS]->store(
3785 						   pos, true));
3786 
3787 					OK(schema_table_store_record(
3788 						   thd, table));
3789 				}
3790 
3791 				++ptr;
3792 
3793 				decoded = ptr - (byte*) node->ilist;
3794 			}
3795 		}
3796 	}
3797 
3798 	i_s_fts_index_table_free_one_fetch(words);
3799 
3800 	DBUG_RETURN(ret);
3801 }
3802 
3803 /*******************************************************************//**
3804 Go through a FTS index and its auxiliary tables, fetch rows in each table
3805 and fill INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE.
3806 @return 0 on success, 1 on failure */
3807 static
3808 int
i_s_fts_index_table_fill_one_index(dict_index_t * index,THD * thd,TABLE_LIST * tables)3809 i_s_fts_index_table_fill_one_index(
3810 /*===============================*/
3811 	dict_index_t*		index,		/*!< in: FTS index */
3812 	THD*			thd,		/*!< in: thread */
3813 	TABLE_LIST*		tables)		/*!< in/out: tables to fill */
3814 {
3815 	ib_vector_t*		words;
3816 	mem_heap_t*		heap;
3817 	CHARSET_INFO*		index_charset;
3818 	fts_string_t		conv_str;
3819 	dberr_t			error;
3820 	int			ret = 0;
3821 
3822 	DBUG_ENTER("i_s_fts_index_table_fill_one_index");
3823 	assert(!dict_index_is_online_ddl(index));
3824 
3825 	heap = mem_heap_create(1024);
3826 
3827 	words = ib_vector_create(ib_heap_allocator_create(heap),
3828 				 sizeof(fts_word_t), 256);
3829 
3830 	index_charset = fts_index_get_charset(index);
3831 	conv_str.f_len = system_charset_info->mbmaxlen
3832 		* FTS_MAX_WORD_LEN_IN_CHAR;
3833 	conv_str.f_str = static_cast<byte*>(ut_malloc_nokey(conv_str.f_len));
3834 	conv_str.f_n_char = 0;
3835 
3836 	/* Iterate through each auxiliary table as described in
3837 	fts_index_selector */
3838 	for (ulint selected = 0; selected < FTS_NUM_AUX_INDEX; selected++) {
3839 		fts_string_t	word;
3840 		bool		has_more = false;
3841 
3842 		word.f_str = NULL;
3843 		word.f_len = 0;
3844 		word.f_n_char = 0;
3845 
3846 		do {
3847 			/* Fetch from index */
3848 			error = i_s_fts_index_table_fill_selected(
3849 				index, words, selected, &word);
3850 
3851 			if (error == DB_SUCCESS) {
3852 				has_more = false;
3853 			} else if (error == DB_FTS_EXCEED_RESULT_CACHE_LIMIT) {
3854 				has_more = true;
3855 			} else {
3856 				i_s_fts_index_table_free_one_fetch(words);
3857 				ret = 1;
3858 				goto func_exit;
3859 			}
3860 
3861 			if (has_more) {
3862 				fts_word_t*	last_word;
3863 
3864 				/* Prepare start point for next fetch */
3865 				last_word = static_cast<fts_word_t*>(ib_vector_last(words));
3866 				ut_ad(last_word != NULL);
3867 				fts_string_dup(&word, &last_word->text, heap);
3868 			}
3869 
3870 			/* Fill into tables */
3871 			ret = i_s_fts_index_table_fill_one_fetch(
3872 				index_charset, thd, tables, words, &conv_str, has_more);
3873 
3874 			if (ret != 0) {
3875 				i_s_fts_index_table_free_one_fetch(words);
3876 				goto func_exit;
3877 			}
3878 		} while (has_more);
3879 	}
3880 
3881 func_exit:
3882 	ut_free(conv_str.f_str);
3883 	mem_heap_free(heap);
3884 
3885 	DBUG_RETURN(ret);
3886 }
3887 /*******************************************************************//**
3888 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3889 @return 0 on success, 1 on failure */
3890 static
3891 int
i_s_fts_index_table_fill(THD * thd,TABLE_LIST * tables,Item *)3892 i_s_fts_index_table_fill(
3893 /*=====================*/
3894 	THD*		thd,	/*!< in: thread */
3895 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
3896 	Item*		)	/*!< in: condition (ignored) */
3897 {
3898 	dict_table_t*		user_table;
3899 	dict_index_t*		index;
3900 
3901 	DBUG_ENTER("i_s_fts_index_table_fill");
3902 
3903 	/* deny access to non-superusers */
3904 	if (check_global_access(thd, PROCESS_ACL)) {
3905 		DBUG_RETURN(0);
3906 	}
3907 
3908         mysql_mutex_lock(&LOCK_global_system_variables);
3909 
3910         if (!fts_internal_tbl_name) {
3911                 mysql_mutex_unlock(&LOCK_global_system_variables);
3912                 DBUG_RETURN(0);
3913         }
3914 
3915 	std::string fts_table_name(fts_internal_tbl_name);
3916 	mysql_mutex_unlock(&LOCK_global_system_variables);
3917 
3918         if(!fts_table_name.c_str()) {
3919                 DBUG_RETURN(0);
3920         }
3921 
3922 	/* Prevent DDL to drop fts aux tables. */
3923 	rw_lock_s_lock(dict_operation_lock);
3924 
3925 	user_table = dict_table_open_on_name(
3926 		fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
3927 
3928 	if (!user_table) {
3929 		rw_lock_s_unlock(dict_operation_lock);
3930 
3931 		DBUG_RETURN(0);
3932 	}
3933 
3934 	for (index = dict_table_get_first_index(user_table);
3935 	     index; index = dict_table_get_next_index(index)) {
3936 		if (index->type & DICT_FTS) {
3937 			i_s_fts_index_table_fill_one_index(index, thd, tables);
3938 		}
3939 	}
3940 
3941 	dict_table_close(user_table, FALSE, FALSE);
3942 
3943 	rw_lock_s_unlock(dict_operation_lock);
3944 
3945 	DBUG_RETURN(0);
3946 }
3947 
3948 /*******************************************************************//**
3949 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE
3950 @return 0 on success */
3951 static
3952 int
i_s_fts_index_table_init(void * p)3953 i_s_fts_index_table_init(
3954 /*=====================*/
3955 	void*	p)	/*!< in/out: table schema object */
3956 {
3957 	DBUG_ENTER("i_s_fts_index_table_init");
3958 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
3959 
3960 	schema->fields_info = i_s_fts_index_fields_info;
3961 	schema->fill_table = i_s_fts_index_table_fill;
3962 
3963 	DBUG_RETURN(0);
3964 }
3965 
3966 struct st_mysql_plugin	i_s_innodb_ft_index_table =
3967 {
3968 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
3969 	/* int */
3970 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
3971 
3972 	/* pointer to type-specific plugin descriptor */
3973 	/* void* */
3974 	STRUCT_FLD(info, &i_s_info),
3975 
3976 	/* plugin name */
3977 	/* const char* */
3978 	STRUCT_FLD(name, "INNODB_FT_INDEX_TABLE"),
3979 
3980 	/* plugin author (for SHOW PLUGINS) */
3981 	/* const char* */
3982 	STRUCT_FLD(author, plugin_author),
3983 
3984 	/* general descriptive text (for SHOW PLUGINS) */
3985 	/* const char* */
3986 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS INDEX TABLE"),
3987 
3988 	/* the plugin license (PLUGIN_LICENSE_XXX) */
3989 	/* int */
3990 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
3991 
3992 	/* the function to invoke when plugin is loaded */
3993 	/* int (*)(void*); */
3994 	STRUCT_FLD(init, i_s_fts_index_table_init),
3995 
3996 	/* the function to invoke when plugin is unloaded */
3997 	/* int (*)(void*); */
3998 	STRUCT_FLD(deinit, i_s_common_deinit),
3999 
4000 	/* plugin version (for SHOW PLUGINS) */
4001 	/* unsigned int */
4002 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
4003 
4004 	/* struct st_mysql_show_var* */
4005 	STRUCT_FLD(status_vars, NULL),
4006 
4007 	/* struct st_mysql_sys_var** */
4008 	STRUCT_FLD(system_vars, NULL),
4009 
4010 	/* reserved for dependency checking */
4011 	/* void* */
4012 	STRUCT_FLD(__reserved1, NULL),
4013 
4014 	/* Plugin flags */
4015 	/* unsigned long */
4016 	STRUCT_FLD(flags, 0UL),
4017 };
4018 
4019 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG */
4020 static ST_FIELD_INFO	i_s_fts_config_fields_info[] =
4021 {
4022 #define	FTS_CONFIG_KEY			0
4023 	{STRUCT_FLD(field_name,		"KEY"),
4024 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
4025 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4026 	 STRUCT_FLD(value,		0),
4027 	 STRUCT_FLD(field_flags,	0),
4028 	 STRUCT_FLD(old_name,		""),
4029 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4030 
4031 #define	FTS_CONFIG_VALUE		1
4032 	{STRUCT_FLD(field_name,		"VALUE"),
4033 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
4034 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4035 	 STRUCT_FLD(value,		0),
4036 	 STRUCT_FLD(field_flags,	0),
4037 	 STRUCT_FLD(old_name,		""),
4038 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4039 
4040 	END_OF_ST_FIELD_INFO
4041 };
4042 
4043 static const char* fts_config_key[] = {
4044 	FTS_OPTIMIZE_LIMIT_IN_SECS,
4045 	FTS_SYNCED_DOC_ID,
4046 	FTS_STOPWORD_TABLE_NAME,
4047 	FTS_USE_STOPWORD,
4048         NULL
4049 };
4050 
4051 /*******************************************************************//**
4052 Fill the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4053 @return 0 on success, 1 on failure */
4054 static
4055 int
i_s_fts_config_fill(THD * thd,TABLE_LIST * tables,Item *)4056 i_s_fts_config_fill(
4057 /*================*/
4058 	THD*		thd,		/*!< in: thread */
4059 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
4060 	Item*		)	/*!< in: condition (ignored) */
4061 {
4062 	Field**			fields;
4063 	TABLE*			table = (TABLE*) tables->table;
4064 	trx_t*			trx;
4065 	fts_table_t		fts_table;
4066 	dict_table_t*		user_table;
4067 	ulint			i = 0;
4068 	dict_index_t*		index = NULL;
4069 	unsigned char		str[FTS_MAX_CONFIG_VALUE_LEN + 1];
4070 
4071 	DBUG_ENTER("i_s_fts_config_fill");
4072 
4073 	/* deny access to non-superusers */
4074 	if (check_global_access(thd, PROCESS_ACL)) {
4075 		DBUG_RETURN(0);
4076 	}
4077 
4078         mysql_mutex_lock(&LOCK_global_system_variables);
4079 
4080         if (!fts_internal_tbl_name) {
4081                 mysql_mutex_unlock(&LOCK_global_system_variables);
4082                 DBUG_RETURN(0);
4083         }
4084 
4085 	std::string fts_table_name(fts_internal_tbl_name);
4086 	mysql_mutex_unlock(&LOCK_global_system_variables);
4087 
4088         if(!fts_table_name.c_str()) {
4089                 DBUG_RETURN(0);
4090         }
4091 
4092 	DEBUG_SYNC_C("i_s_fts_config_fille_check");
4093 
4094 	fields = table->field;
4095 
4096 	/* Prevent DDL to drop fts aux tables. */
4097 	rw_lock_s_lock(dict_operation_lock);
4098 
4099 	user_table = dict_table_open_on_name(
4100 		fts_table_name.c_str(), FALSE, FALSE, DICT_ERR_IGNORE_NONE);
4101 
4102 	if (!user_table) {
4103 		rw_lock_s_unlock(dict_operation_lock);
4104 
4105 		DBUG_RETURN(0);
4106 	} else if (!dict_table_has_fts_index(user_table)) {
4107 		dict_table_close(user_table, FALSE, FALSE);
4108 
4109 		rw_lock_s_unlock(dict_operation_lock);
4110 
4111 		DBUG_RETURN(0);
4112 	}
4113 
4114 	trx = trx_allocate_for_background();
4115 	trx->op_info = "Select for FTS CONFIG TABLE";
4116 
4117 	FTS_INIT_FTS_TABLE(&fts_table, "CONFIG", FTS_COMMON_TABLE, user_table);
4118 
4119 	if (!ib_vector_is_empty(user_table->fts->indexes)) {
4120 		index = (dict_index_t*) ib_vector_getp_const(
4121 				user_table->fts->indexes, 0);
4122 		assert(!dict_index_is_online_ddl(index));
4123 	}
4124 
4125 	while (fts_config_key[i]) {
4126 		fts_string_t	value;
4127 		char*		key_name;
4128 		ulint		allocated = FALSE;
4129 
4130 		value.f_len = FTS_MAX_CONFIG_VALUE_LEN;
4131 
4132 		value.f_str = str;
4133 
4134 		if (index
4135 		    && strcmp(fts_config_key[i], FTS_TOTAL_WORD_COUNT) == 0) {
4136 			key_name = fts_config_create_index_param_name(
4137 				fts_config_key[i], index);
4138 			allocated = TRUE;
4139 		} else {
4140 			key_name = (char*) fts_config_key[i];
4141 		}
4142 
4143 		fts_config_get_value(trx, &fts_table, key_name, &value);
4144 
4145 		if (allocated) {
4146 			ut_free(key_name);
4147 		}
4148 
4149 		OK(field_store_string(
4150                         fields[FTS_CONFIG_KEY], fts_config_key[i]));
4151 
4152 		OK(field_store_string(
4153                         fields[FTS_CONFIG_VALUE], (const char*) value.f_str));
4154 
4155 		OK(schema_table_store_record(thd, table));
4156 
4157 		i++;
4158 	}
4159 
4160 	fts_sql_commit(trx);
4161 
4162 	trx_free_for_background(trx);
4163 
4164 	dict_table_close(user_table, FALSE, FALSE);
4165 
4166 	rw_lock_s_unlock(dict_operation_lock);
4167 
4168 	DBUG_RETURN(0);
4169 }
4170 
4171 /*******************************************************************//**
4172 Bind the dynamic table INFORMATION_SCHEMA.INNODB_FT_CONFIG
4173 @return 0 on success */
4174 static
4175 int
i_s_fts_config_init(void * p)4176 i_s_fts_config_init(
4177 /*=================*/
4178 	void*	p)	/*!< in/out: table schema object */
4179 {
4180 	DBUG_ENTER("i_s_fts_config_init");
4181 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
4182 
4183 	schema->fields_info = i_s_fts_config_fields_info;
4184 	schema->fill_table = i_s_fts_config_fill;
4185 
4186 	DBUG_RETURN(0);
4187 }
4188 
4189 struct st_mysql_plugin	i_s_innodb_ft_config =
4190 {
4191 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
4192 	/* int */
4193 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4194 
4195 	/* pointer to type-specific plugin descriptor */
4196 	/* void* */
4197 	STRUCT_FLD(info, &i_s_info),
4198 
4199 	/* plugin name */
4200 	/* const char* */
4201 	STRUCT_FLD(name, "INNODB_FT_CONFIG"),
4202 
4203 	/* plugin author (for SHOW PLUGINS) */
4204 	/* const char* */
4205 	STRUCT_FLD(author, plugin_author),
4206 
4207 	/* general descriptive text (for SHOW PLUGINS) */
4208 	/* const char* */
4209 	STRUCT_FLD(descr, "INNODB AUXILIARY FTS CONFIG TABLE"),
4210 
4211 	/* the plugin license (PLUGIN_LICENSE_XXX) */
4212 	/* int */
4213 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4214 
4215 	/* the function to invoke when plugin is loaded */
4216 	/* int (*)(void*); */
4217 	STRUCT_FLD(init, i_s_fts_config_init),
4218 
4219 	/* the function to invoke when plugin is unloaded */
4220 	/* int (*)(void*); */
4221 	STRUCT_FLD(deinit, i_s_common_deinit),
4222 
4223 	/* plugin version (for SHOW PLUGINS) */
4224 	/* unsigned int */
4225 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
4226 
4227 	/* struct st_mysql_show_var* */
4228 	STRUCT_FLD(status_vars, NULL),
4229 
4230 	/* struct st_mysql_sys_var** */
4231 	STRUCT_FLD(system_vars, NULL),
4232 
4233 	/* reserved for dependency checking */
4234 	/* void* */
4235 	STRUCT_FLD(__reserved1, NULL),
4236 
4237 	/* Plugin flags */
4238 	/* unsigned long */
4239 	STRUCT_FLD(flags, 0UL),
4240 };
4241 
4242 /* Fields of the dynamic table INNODB_TEMP_TABLE_INFO. */
4243 static ST_FIELD_INFO	i_s_innodb_temp_table_info_fields_info[] =
4244 {
4245 #define IDX_TEMP_TABLE_ID		0
4246 	{STRUCT_FLD(field_name,		"TABLE_ID"),
4247 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4248 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4249 	 STRUCT_FLD(value,		0),
4250 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4251 	 STRUCT_FLD(old_name,		""),
4252 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4253 
4254 #define IDX_TEMP_TABLE_NAME		1
4255 	{STRUCT_FLD(field_name,		"NAME"),
4256 	 STRUCT_FLD(field_length,	MAX_TABLE_UTF8_LEN),
4257 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4258 	 STRUCT_FLD(value,		0),
4259 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4260 	 STRUCT_FLD(old_name,		""),
4261 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4262 
4263 #define IDX_TEMP_TABLE_N_COLS		2
4264 	{STRUCT_FLD(field_name,		"N_COLS"),
4265 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
4266 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
4267 	 STRUCT_FLD(value,		0),
4268 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4269 	 STRUCT_FLD(old_name,		""),
4270 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4271 
4272 #define IDX_TEMP_TABLE_SPACE_ID		3
4273 	{STRUCT_FLD(field_name,		"SPACE"),
4274 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
4275 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
4276 	 STRUCT_FLD(value,		0),
4277 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4278 	 STRUCT_FLD(old_name,		""),
4279 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4280 
4281 #define IDX_TEMP_TABLE_PTT		4
4282 	{STRUCT_FLD(field_name,		"PER_TABLE_TABLESPACE"),
4283 	 STRUCT_FLD(field_length,	64),
4284 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4285 	 STRUCT_FLD(value,		0),
4286 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4287 	 STRUCT_FLD(old_name,		""),
4288 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4289 
4290 #define IDX_TEMP_TABLE_IS_COMPRESSED	5
4291 	{STRUCT_FLD(field_name,		"IS_COMPRESSED"),
4292 	 STRUCT_FLD(field_length,	64),
4293 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
4294 	 STRUCT_FLD(value,		0),
4295 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
4296 	 STRUCT_FLD(old_name,		""),
4297 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4298 	END_OF_ST_FIELD_INFO
4299 };
4300 
4301 struct temp_table_info_t{
4302 	table_id_t	m_table_id;
4303 	char		m_table_name[MAX_TABLE_UTF8_LEN];
4304 	unsigned	m_n_cols;
4305 	unsigned	m_space_id;
4306 	char		m_per_table_tablespace[64];
4307 	char		m_is_compressed[64];
4308 };
4309 
4310 typedef std::vector<temp_table_info_t, ut_allocator<temp_table_info_t> >
4311 	temp_table_info_cache_t;
4312 
4313 /*******************************************************************//**
4314 Fill Information Schema table INNODB_TEMP_TABLE_INFO for a particular
4315 temp-table
4316 @return 0 on success, 1 on failure */
4317 static
4318 int
i_s_innodb_temp_table_info_fill(THD * thd,TABLE_LIST * tables,const temp_table_info_t * info)4319 i_s_innodb_temp_table_info_fill(
4320 /*=============================*/
4321 	THD*				thd,		/*!< in: thread */
4322 	TABLE_LIST*			tables,		/*!< in/out: tables
4323 							to fill */
4324 	const temp_table_info_t*	info)		/*!< in: temp-table
4325 							information */
4326 {
4327 	TABLE*			table;
4328 	Field**			fields;
4329 
4330 	DBUG_ENTER("i_s_innodb_temp_table_info_fill");
4331 
4332 	table = tables->table;
4333 
4334 	fields = table->field;
4335 
4336 	OK(fields[IDX_TEMP_TABLE_ID]->store(info->m_table_id, true));
4337 
4338 	OK(field_store_string(
4339 		   fields[IDX_TEMP_TABLE_NAME], info->m_table_name));
4340 
4341 	OK(fields[IDX_TEMP_TABLE_N_COLS]->store(info->m_n_cols));
4342 
4343 	OK(fields[IDX_TEMP_TABLE_SPACE_ID]->store(info->m_space_id));
4344 
4345 	OK(field_store_string(
4346 		fields[IDX_TEMP_TABLE_PTT], info->m_per_table_tablespace));
4347 
4348 	OK(field_store_string(
4349 		fields[IDX_TEMP_TABLE_IS_COMPRESSED], info->m_is_compressed));
4350 
4351 	DBUG_RETURN(schema_table_store_record(thd, table));
4352 }
4353 
4354 /*******************************************************************//**
4355 Populate current table information to cache */
4356 static
4357 void
innodb_temp_table_populate_cache(const dict_table_t * table,temp_table_info_t * cache)4358 innodb_temp_table_populate_cache(
4359 /*=============================*/
4360 	const dict_table_t*	table,  /*! in: table */
4361 	temp_table_info_t*	cache)  /*! in/out: populate data in this
4362 					cache */
4363 {
4364 	cache->m_table_id = table->id;
4365 
4366 	char	db_utf8[MAX_DB_UTF8_LEN];
4367 	char	table_utf8[MAX_TABLE_UTF8_LEN];
4368 
4369 	dict_fs2utf8(table->name.m_name,
4370 		     db_utf8, sizeof(db_utf8),
4371 		     table_utf8, sizeof(table_utf8));
4372 	strcpy(cache->m_table_name, table_utf8);
4373 
4374 	cache->m_n_cols = table->n_cols;
4375 
4376 	cache->m_space_id = table->space;
4377 
4378 	if (fsp_is_system_temporary(table->space)) {
4379 		strcpy(cache->m_per_table_tablespace, "FALSE");
4380 	} else {
4381 		strcpy(cache->m_per_table_tablespace, "TRUE");
4382 	}
4383 
4384 	if (dict_table_page_size(table).is_compressed()) {
4385 		strcpy(cache->m_is_compressed, "TRUE");
4386 	} else {
4387 		strcpy(cache->m_is_compressed, "FALSE");
4388 	}
4389 }
4390 
4391 /*******************************************************************//**
4392 This function will iterate over all available table and will fill
4393 stats for temp-tables to INNODB_TEMP_TABLE_INFO.
4394 @return 0 on success, 1 on failure */
4395 static
4396 int
i_s_innodb_temp_table_info_fill_table(THD * thd,TABLE_LIST * tables,Item *)4397 i_s_innodb_temp_table_info_fill_table(
4398 /*===================================*/
4399 	THD*		thd,		/*!< in: thread */
4400 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
4401 	Item*		)		/*!< in: condition (ignored) */
4402 {
4403 	int			status	= 0;
4404 	dict_table_t*		table	= NULL;
4405 
4406 	DBUG_ENTER("i_s_innodb_temp_table_info_fill_table");
4407 
4408 	/* Only allow the PROCESS privilege holder to access the stats */
4409 	if (check_global_access(thd, PROCESS_ACL)) {
4410 		DBUG_RETURN(0);
4411 	}
4412 
4413 	/* First populate all temp-table info by acquiring dict_sys->mutex.
4414 	Note: Scan is being done on NON-LRU list which mainly has system
4415 	table entries and temp-table entries. This means 2 things: list
4416 	is smaller so processing would be faster and most of the data
4417 	is relevant */
4418 	temp_table_info_cache_t all_temp_info_cache;
4419 	all_temp_info_cache.reserve(UT_LIST_GET_LEN(dict_sys->table_non_LRU));
4420 
4421 	mutex_enter(&dict_sys->mutex);
4422 	for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU);
4423 	     table != NULL;
4424 	     table = UT_LIST_GET_NEXT(table_LRU, table)) {
4425 
4426 		if (!dict_table_is_temporary(table)) {
4427 			continue;
4428 		}
4429 
4430 		temp_table_info_t current_temp_table_info;
4431 
4432 		innodb_temp_table_populate_cache(
4433 			table, &current_temp_table_info);
4434 
4435 		all_temp_info_cache.push_back(current_temp_table_info);
4436 	}
4437 	mutex_exit(&dict_sys->mutex);
4438 
4439 	/* Now populate the info to MySQL table */
4440 	temp_table_info_cache_t::const_iterator end = all_temp_info_cache.end();
4441 	for (temp_table_info_cache_t::const_iterator it
4442 		= all_temp_info_cache.begin();
4443 	     it != end;
4444 	     it++) {
4445 		status = i_s_innodb_temp_table_info_fill(thd, tables, &(*it));
4446 		if (status) {
4447 			break;
4448 		}
4449 	}
4450 
4451 	DBUG_RETURN(status);
4452 }
4453 
4454 /*******************************************************************//**
4455 Bind the dynamic table INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO.
4456 @return 0 on success, 1 on failure */
4457 static
4458 int
i_s_innodb_temp_table_info_init(void * p)4459 i_s_innodb_temp_table_info_init(
4460 /*=============================*/
4461 	void*	p)	/*!< in/out: table schema object */
4462 {
4463 	ST_SCHEMA_TABLE*	schema;
4464 
4465 	DBUG_ENTER("i_s_innodb_temp_table_info_init");
4466 
4467 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
4468 
4469 	schema->fields_info = i_s_innodb_temp_table_info_fields_info;
4470 	schema->fill_table = i_s_innodb_temp_table_info_fill_table;
4471 
4472 	DBUG_RETURN(0);
4473 }
4474 
4475 struct st_mysql_plugin	i_s_innodb_temp_table_info =
4476 {
4477 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
4478 	/* int */
4479 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
4480 
4481 	/* pointer to type-specific plugin descriptor */
4482 	/* void* */
4483 	STRUCT_FLD(info, &i_s_info),
4484 
4485 	/* plugin name */
4486 	/* const char* */
4487 	STRUCT_FLD(name, "INNODB_TEMP_TABLE_INFO"),
4488 
4489 	/* plugin author (for SHOW PLUGINS) */
4490 	/* const char* */
4491 	STRUCT_FLD(author, plugin_author),
4492 
4493 	/* general descriptive text (for SHOW PLUGINS) */
4494 	/* const char* */
4495 	STRUCT_FLD(descr, "InnoDB Temp Table Stats"),
4496 
4497 	/* the plugin license (PLUGIN_LICENSE_XXX) */
4498 	/* int */
4499 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
4500 
4501 	/* the function to invoke when plugin is loaded */
4502 	/* int (*)(void*); */
4503 	STRUCT_FLD(init, i_s_innodb_temp_table_info_init),
4504 
4505 	/* the function to invoke when plugin is unloaded */
4506 	/* int (*)(void*); */
4507 	STRUCT_FLD(deinit, i_s_common_deinit),
4508 
4509 	/* plugin version (for SHOW PLUGINS) */
4510 	/* unsigned int */
4511 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
4512 
4513 	/* struct st_mysql_show_var* */
4514 	STRUCT_FLD(status_vars, NULL),
4515 
4516 	/* struct st_mysql_sys_var** */
4517 	STRUCT_FLD(system_vars, NULL),
4518 
4519 	/* reserved for dependency checking */
4520 	/* void* */
4521 	STRUCT_FLD(__reserved1, NULL),
4522 
4523 	/* Plugin flags */
4524 	/* unsigned long */
4525 	STRUCT_FLD(flags, 0UL),
4526 };
4527 
4528 /* Fields of the dynamic table INNODB_BUFFER_POOL_STATS. */
4529 static ST_FIELD_INFO	i_s_innodb_buffer_stats_fields_info[] =
4530 {
4531 #define IDX_BUF_STATS_POOL_ID		0
4532 	{STRUCT_FLD(field_name,		"POOL_ID"),
4533 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4534 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4535 	 STRUCT_FLD(value,		0),
4536 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4537 	 STRUCT_FLD(old_name,		""),
4538 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4539 
4540 #define IDX_BUF_STATS_POOL_SIZE		1
4541 	{STRUCT_FLD(field_name,		"POOL_SIZE"),
4542 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4543 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4544 	 STRUCT_FLD(value,		0),
4545 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4546 	 STRUCT_FLD(old_name,		""),
4547 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4548 
4549 #define IDX_BUF_STATS_FREE_BUFFERS	2
4550 	{STRUCT_FLD(field_name,		"FREE_BUFFERS"),
4551 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4552 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4553 	 STRUCT_FLD(value,		0),
4554 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4555 	 STRUCT_FLD(old_name,		""),
4556 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4557 
4558 #define IDX_BUF_STATS_LRU_LEN		3
4559 	{STRUCT_FLD(field_name,		"DATABASE_PAGES"),
4560 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4561 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4562 	 STRUCT_FLD(value,		0),
4563 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4564 	 STRUCT_FLD(old_name,		""),
4565 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4566 
4567 #define IDX_BUF_STATS_OLD_LRU_LEN	4
4568 	{STRUCT_FLD(field_name,		"OLD_DATABASE_PAGES"),
4569 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4570 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4571 	 STRUCT_FLD(value,		0),
4572 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4573 	 STRUCT_FLD(old_name,		""),
4574 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4575 
4576 #define IDX_BUF_STATS_FLUSH_LIST_LEN	5
4577 	{STRUCT_FLD(field_name,		"MODIFIED_DATABASE_PAGES"),
4578 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4579 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4580 	 STRUCT_FLD(value,		0),
4581 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4582 	 STRUCT_FLD(old_name,		""),
4583 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4584 
4585 #define IDX_BUF_STATS_PENDING_ZIP	6
4586 	{STRUCT_FLD(field_name,		"PENDING_DECOMPRESS"),
4587 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4588 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4589 	 STRUCT_FLD(value,		0),
4590 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4591 	 STRUCT_FLD(old_name,		""),
4592 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4593 
4594 #define IDX_BUF_STATS_PENDING_READ	7
4595 	{STRUCT_FLD(field_name,		"PENDING_READS"),
4596 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4597 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4598 	 STRUCT_FLD(value,		0),
4599 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4600 	 STRUCT_FLD(old_name,		""),
4601 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4602 
4603 #define IDX_BUF_STATS_FLUSH_LRU		8
4604 	{STRUCT_FLD(field_name,		"PENDING_FLUSH_LRU"),
4605 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4606 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4607 	 STRUCT_FLD(value,		0),
4608 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4609 	 STRUCT_FLD(old_name,		""),
4610 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4611 
4612 #define IDX_BUF_STATS_FLUSH_LIST	9
4613 	{STRUCT_FLD(field_name,		"PENDING_FLUSH_LIST"),
4614 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4615 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4616 	 STRUCT_FLD(value,		0),
4617 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4618 	 STRUCT_FLD(old_name,		""),
4619 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4620 
4621 #define IDX_BUF_STATS_PAGE_YOUNG	10
4622 	{STRUCT_FLD(field_name,		"PAGES_MADE_YOUNG"),
4623 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4624 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4625 	 STRUCT_FLD(value,		0),
4626 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4627 	 STRUCT_FLD(old_name,		""),
4628 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4629 
4630 #define IDX_BUF_STATS_PAGE_NOT_YOUNG	11
4631 	{STRUCT_FLD(field_name,		"PAGES_NOT_MADE_YOUNG"),
4632 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4633 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4634 	 STRUCT_FLD(value,		0),
4635 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4636 	 STRUCT_FLD(old_name,		""),
4637 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4638 
4639 #define	IDX_BUF_STATS_PAGE_YOUNG_RATE	12
4640 	{STRUCT_FLD(field_name,		"PAGES_MADE_YOUNG_RATE"),
4641 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4642 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4643 	 STRUCT_FLD(value,		0),
4644 	 STRUCT_FLD(field_flags,	0),
4645 	 STRUCT_FLD(old_name,		""),
4646 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4647 
4648 #define	IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE 13
4649 	{STRUCT_FLD(field_name,		"PAGES_MADE_NOT_YOUNG_RATE"),
4650 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4651 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4652 	 STRUCT_FLD(value,		0),
4653 	 STRUCT_FLD(field_flags,	0),
4654 	 STRUCT_FLD(old_name,		""),
4655 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4656 
4657 #define IDX_BUF_STATS_PAGE_READ		14
4658 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_READ"),
4659 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4660 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4661 	 STRUCT_FLD(value,		0),
4662 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4663 	 STRUCT_FLD(old_name,		""),
4664 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4665 
4666 #define IDX_BUF_STATS_PAGE_CREATED	15
4667 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_CREATED"),
4668 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4669 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4670 	 STRUCT_FLD(value,		0),
4671 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4672 	 STRUCT_FLD(old_name,		""),
4673 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4674 
4675 #define IDX_BUF_STATS_PAGE_WRITTEN	16
4676 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_WRITTEN"),
4677 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4678 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4679 	 STRUCT_FLD(value,		0),
4680 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4681 	 STRUCT_FLD(old_name,		""),
4682 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4683 
4684 #define	IDX_BUF_STATS_PAGE_READ_RATE	17
4685 	{STRUCT_FLD(field_name,		"PAGES_READ_RATE"),
4686 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4687 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4688 	 STRUCT_FLD(value,		0),
4689 	 STRUCT_FLD(field_flags,	0),
4690 	 STRUCT_FLD(old_name,		""),
4691 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4692 
4693 #define	IDX_BUF_STATS_PAGE_CREATE_RATE	18
4694 	{STRUCT_FLD(field_name,		"PAGES_CREATE_RATE"),
4695 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4696 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4697 	 STRUCT_FLD(value,		0),
4698 	 STRUCT_FLD(field_flags,	0),
4699 	 STRUCT_FLD(old_name,		""),
4700 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4701 
4702 #define	IDX_BUF_STATS_PAGE_WRITTEN_RATE	19
4703 	{STRUCT_FLD(field_name,		"PAGES_WRITTEN_RATE"),
4704 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4705 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4706 	 STRUCT_FLD(value,		0),
4707 	 STRUCT_FLD(field_flags,	0),
4708 	 STRUCT_FLD(old_name,		""),
4709 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4710 
4711 #define IDX_BUF_STATS_GET		20
4712 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_GET"),
4713 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4714 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4715 	 STRUCT_FLD(value,		0),
4716 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4717 	 STRUCT_FLD(old_name,		""),
4718 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4719 
4720 #define IDX_BUF_STATS_HIT_RATE		21
4721 	{STRUCT_FLD(field_name,		"HIT_RATE"),
4722 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4723 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4724 	 STRUCT_FLD(value,		0),
4725 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4726 	 STRUCT_FLD(old_name,		""),
4727 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4728 
4729 #define IDX_BUF_STATS_MADE_YOUNG_PCT	22
4730 	{STRUCT_FLD(field_name,		"YOUNG_MAKE_PER_THOUSAND_GETS"),
4731 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4732 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4733 	 STRUCT_FLD(value,		0),
4734 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4735 	 STRUCT_FLD(old_name,		""),
4736 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4737 
4738 #define IDX_BUF_STATS_NOT_MADE_YOUNG_PCT 23
4739 	{STRUCT_FLD(field_name,		"NOT_YOUNG_MAKE_PER_THOUSAND_GETS"),
4740 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4741 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4742 	 STRUCT_FLD(value,		0),
4743 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4744 	 STRUCT_FLD(old_name,		""),
4745 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4746 
4747 #define IDX_BUF_STATS_READ_AHREAD	24
4748 	{STRUCT_FLD(field_name,		"NUMBER_PAGES_READ_AHEAD"),
4749 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4750 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4751 	 STRUCT_FLD(value,		0),
4752 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4753 	 STRUCT_FLD(old_name,		""),
4754 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4755 
4756 #define IDX_BUF_STATS_READ_AHEAD_EVICTED 25
4757 	{STRUCT_FLD(field_name,		"NUMBER_READ_AHEAD_EVICTED"),
4758 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4759 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4760 	 STRUCT_FLD(value,		0),
4761 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4762 	 STRUCT_FLD(old_name,		""),
4763 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4764 
4765 #define	IDX_BUF_STATS_READ_AHEAD_RATE	26
4766 	{STRUCT_FLD(field_name,		"READ_AHEAD_RATE"),
4767 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4768 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4769 	 STRUCT_FLD(value,		0),
4770 	 STRUCT_FLD(field_flags,	0),
4771 	 STRUCT_FLD(old_name,		""),
4772 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4773 
4774 #define	IDX_BUF_STATS_READ_AHEAD_EVICT_RATE 27
4775 	{STRUCT_FLD(field_name,		"READ_AHEAD_EVICTED_RATE"),
4776 	 STRUCT_FLD(field_length,	MAX_FLOAT_STR_LENGTH),
4777 	 STRUCT_FLD(field_type,		MYSQL_TYPE_FLOAT),
4778 	 STRUCT_FLD(value,		0),
4779 	 STRUCT_FLD(field_flags,	0),
4780 	 STRUCT_FLD(old_name,		""),
4781 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4782 
4783 #define IDX_BUF_STATS_LRU_IO_SUM	28
4784 	{STRUCT_FLD(field_name,		"LRU_IO_TOTAL"),
4785 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4786 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4787 	 STRUCT_FLD(value,		0),
4788 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4789 	 STRUCT_FLD(old_name,		""),
4790 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4791 
4792 #define IDX_BUF_STATS_LRU_IO_CUR	29
4793 	{STRUCT_FLD(field_name,		"LRU_IO_CURRENT"),
4794 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4795 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4796 	 STRUCT_FLD(value,		0),
4797 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4798 	 STRUCT_FLD(old_name,		""),
4799 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4800 
4801 #define IDX_BUF_STATS_UNZIP_SUM		30
4802 	{STRUCT_FLD(field_name,		"UNCOMPRESS_TOTAL"),
4803 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4804 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4805 	 STRUCT_FLD(value,		0),
4806 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4807 	 STRUCT_FLD(old_name,		""),
4808 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4809 
4810 #define IDX_BUF_STATS_UNZIP_CUR		31
4811 	{STRUCT_FLD(field_name,		"UNCOMPRESS_CURRENT"),
4812 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
4813 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
4814 	 STRUCT_FLD(value,		0),
4815 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
4816 	 STRUCT_FLD(old_name,		""),
4817 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
4818 
4819 	END_OF_ST_FIELD_INFO
4820 };
4821 
4822 /*******************************************************************//**
4823 Fill Information Schema table INNODB_BUFFER_POOL_STATS for a particular
4824 buffer pool
4825 @return 0 on success, 1 on failure */
4826 static
4827 int
i_s_innodb_stats_fill(THD * thd,TABLE_LIST * tables,const buf_pool_info_t * info)4828 i_s_innodb_stats_fill(
4829 /*==================*/
4830 	THD*			thd,		/*!< in: thread */
4831 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
4832 	const buf_pool_info_t*	info)		/*!< in: buffer pool
4833 						information */
4834 {
4835 	TABLE*			table;
4836 	Field**			fields;
4837 
4838 	DBUG_ENTER("i_s_innodb_stats_fill");
4839 
4840 	table = tables->table;
4841 
4842 	fields = table->field;
4843 
4844 	OK(fields[IDX_BUF_STATS_POOL_ID]->store(
4845 		   info->pool_unique_id, true));
4846 
4847 	OK(fields[IDX_BUF_STATS_POOL_SIZE]->store(
4848 		   info->pool_size, true));
4849 
4850 	OK(fields[IDX_BUF_STATS_LRU_LEN]->store(
4851 		   info->lru_len, true));
4852 
4853 	OK(fields[IDX_BUF_STATS_OLD_LRU_LEN]->store(
4854 		   info->old_lru_len, true));
4855 
4856 	OK(fields[IDX_BUF_STATS_FREE_BUFFERS]->store(
4857 		   info->free_list_len, true));
4858 
4859 	OK(fields[IDX_BUF_STATS_FLUSH_LIST_LEN]->store(
4860 		   info->flush_list_len, true));
4861 
4862 	OK(fields[IDX_BUF_STATS_PENDING_ZIP]->store(
4863 		   info->n_pend_unzip, true));
4864 
4865 	OK(fields[IDX_BUF_STATS_PENDING_READ]->store(
4866 		   info->n_pend_reads, true));
4867 
4868 	OK(fields[IDX_BUF_STATS_FLUSH_LRU]->store(
4869 		   info->n_pending_flush_lru, true));
4870 
4871 	OK(fields[IDX_BUF_STATS_FLUSH_LIST]->store(
4872 		   info->n_pending_flush_list, true));
4873 
4874 	OK(fields[IDX_BUF_STATS_PAGE_YOUNG]->store(
4875 		   info->n_pages_made_young, true));
4876 
4877 	OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG]->store(
4878 		   info->n_pages_not_made_young, true));
4879 
4880 	OK(fields[IDX_BUF_STATS_PAGE_YOUNG_RATE]->store(
4881 		   info->page_made_young_rate));
4882 
4883 	OK(fields[IDX_BUF_STATS_PAGE_NOT_YOUNG_RATE]->store(
4884 		   info->page_not_made_young_rate));
4885 
4886 	OK(fields[IDX_BUF_STATS_PAGE_READ]->store(
4887 		   info->n_pages_read, true));
4888 
4889 	OK(fields[IDX_BUF_STATS_PAGE_CREATED]->store(
4890 		   info->n_pages_created, true));
4891 
4892 	OK(fields[IDX_BUF_STATS_PAGE_WRITTEN]->store(
4893 		   info->n_pages_written, true));
4894 
4895 	OK(fields[IDX_BUF_STATS_GET]->store(
4896 		   info->n_page_gets, true));
4897 
4898 	OK(fields[IDX_BUF_STATS_PAGE_READ_RATE]->store(
4899 		   info->pages_read_rate));
4900 
4901 	OK(fields[IDX_BUF_STATS_PAGE_CREATE_RATE]->store(
4902 		   info->pages_created_rate));
4903 
4904 	OK(fields[IDX_BUF_STATS_PAGE_WRITTEN_RATE]->store(
4905 		   info->pages_written_rate));
4906 
4907 	if (info->n_page_get_delta) {
4908 		OK(fields[IDX_BUF_STATS_HIT_RATE]->store(
4909 			   1000 - (1000 * info->page_read_delta
4910 				   / info->n_page_get_delta), true));
4911 
4912 		OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(
4913 			   1000 * info->young_making_delta
4914 			   / info->n_page_get_delta, true));
4915 
4916 		OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(
4917 			   1000 * info->not_young_making_delta
4918 			   / info->n_page_get_delta, true));
4919 	} else {
4920 		OK(fields[IDX_BUF_STATS_HIT_RATE]->store(0, true));
4921 		OK(fields[IDX_BUF_STATS_MADE_YOUNG_PCT]->store(0, true));
4922 		OK(fields[IDX_BUF_STATS_NOT_MADE_YOUNG_PCT]->store(0, true));
4923 	}
4924 
4925 	OK(fields[IDX_BUF_STATS_READ_AHREAD]->store(
4926 		   info->n_ra_pages_read, true));
4927 
4928 	OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICTED]->store(
4929 		   info->n_ra_pages_evicted, true));
4930 
4931 	OK(fields[IDX_BUF_STATS_READ_AHEAD_RATE]->store(
4932 		   info->pages_readahead_rate));
4933 
4934 	OK(fields[IDX_BUF_STATS_READ_AHEAD_EVICT_RATE]->store(
4935 		   info->pages_evicted_rate));
4936 
4937 	OK(fields[IDX_BUF_STATS_LRU_IO_SUM]->store(
4938 		   info->io_sum, true));
4939 
4940 	OK(fields[IDX_BUF_STATS_LRU_IO_CUR]->store(
4941 		   info->io_cur, true));
4942 
4943 	OK(fields[IDX_BUF_STATS_UNZIP_SUM]->store(
4944 		   info->unzip_sum, true));
4945 
4946 	OK(fields[IDX_BUF_STATS_UNZIP_CUR]->store(
4947 		   info->unzip_cur, true));
4948 
4949 	DBUG_RETURN(schema_table_store_record(thd, table));
4950 }
4951 
4952 /*******************************************************************//**
4953 This is the function that loops through each buffer pool and fetch buffer
4954 pool stats to information schema  table: I_S_INNODB_BUFFER_POOL_STATS
4955 @return 0 on success, 1 on failure */
4956 static
4957 int
i_s_innodb_buffer_stats_fill_table(THD * thd,TABLE_LIST * tables,Item *)4958 i_s_innodb_buffer_stats_fill_table(
4959 /*===============================*/
4960 	THD*		thd,		/*!< in: thread */
4961 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
4962 	Item*		)		/*!< in: condition (ignored) */
4963 {
4964 	int			status	= 0;
4965 	buf_pool_info_t*	pool_info;
4966 
4967 	DBUG_ENTER("i_s_innodb_buffer_fill_general");
4968 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
4969 
4970 	/* Only allow the PROCESS privilege holder to access the stats */
4971 	if (check_global_access(thd, PROCESS_ACL)) {
4972 		DBUG_RETURN(0);
4973 	}
4974 
4975 	pool_info = (buf_pool_info_t*) ut_zalloc_nokey(
4976 		srv_buf_pool_instances *  sizeof *pool_info);
4977 
4978 	/* Walk through each buffer pool */
4979 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
4980 		buf_pool_t*		buf_pool;
4981 
4982 		buf_pool = buf_pool_from_array(i);
4983 
4984 		/* Fetch individual buffer pool info */
4985 		buf_stats_get_pool_info(buf_pool, i, pool_info);
4986 
4987 		status = i_s_innodb_stats_fill(thd, tables, &pool_info[i]);
4988 
4989 		/* If something goes wrong, break and return */
4990 		if (status) {
4991 			break;
4992 		}
4993 	}
4994 
4995 	ut_free(pool_info);
4996 
4997 	DBUG_RETURN(status);
4998 }
4999 
5000 /*******************************************************************//**
5001 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS.
5002 @return 0 on success, 1 on failure */
5003 static
5004 int
i_s_innodb_buffer_pool_stats_init(void * p)5005 i_s_innodb_buffer_pool_stats_init(
5006 /*==============================*/
5007 	void*	p)	/*!< in/out: table schema object */
5008 {
5009 	ST_SCHEMA_TABLE*	schema;
5010 
5011 	DBUG_ENTER("i_s_innodb_buffer_pool_stats_init");
5012 
5013 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
5014 
5015 	schema->fields_info = i_s_innodb_buffer_stats_fields_info;
5016 	schema->fill_table = i_s_innodb_buffer_stats_fill_table;
5017 
5018 	DBUG_RETURN(0);
5019 }
5020 
5021 struct st_mysql_plugin	i_s_innodb_buffer_stats =
5022 {
5023 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
5024 	/* int */
5025 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
5026 
5027 	/* pointer to type-specific plugin descriptor */
5028 	/* void* */
5029 	STRUCT_FLD(info, &i_s_info),
5030 
5031 	/* plugin name */
5032 	/* const char* */
5033 	STRUCT_FLD(name, "INNODB_BUFFER_POOL_STATS"),
5034 
5035 	/* plugin author (for SHOW PLUGINS) */
5036 	/* const char* */
5037 	STRUCT_FLD(author, plugin_author),
5038 
5039 	/* general descriptive text (for SHOW PLUGINS) */
5040 	/* const char* */
5041 	STRUCT_FLD(descr, "InnoDB Buffer Pool Statistics Information "),
5042 
5043 	/* the plugin license (PLUGIN_LICENSE_XXX) */
5044 	/* int */
5045 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
5046 
5047 	/* the function to invoke when plugin is loaded */
5048 	/* int (*)(void*); */
5049 	STRUCT_FLD(init, i_s_innodb_buffer_pool_stats_init),
5050 
5051 	/* the function to invoke when plugin is unloaded */
5052 	/* int (*)(void*); */
5053 	STRUCT_FLD(deinit, i_s_common_deinit),
5054 
5055 	/* plugin version (for SHOW PLUGINS) */
5056 	/* unsigned int */
5057 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
5058 
5059 	/* struct st_mysql_show_var* */
5060 	STRUCT_FLD(status_vars, NULL),
5061 
5062 	/* struct st_mysql_sys_var** */
5063 	STRUCT_FLD(system_vars, NULL),
5064 
5065 	/* reserved for dependency checking */
5066 	/* void* */
5067 	STRUCT_FLD(__reserved1, NULL),
5068 
5069 	/* Plugin flags */
5070 	/* unsigned long */
5071 	STRUCT_FLD(flags, 0UL),
5072 };
5073 
5074 /* Fields of the dynamic table INNODB_BUFFER_POOL_PAGE. */
5075 static ST_FIELD_INFO	i_s_innodb_buffer_page_fields_info[] =
5076 {
5077 #define IDX_BUFFER_POOL_ID		0
5078 	{STRUCT_FLD(field_name,		"POOL_ID"),
5079 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5080 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5081 	 STRUCT_FLD(value,		0),
5082 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5083 	 STRUCT_FLD(old_name,		""),
5084 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5085 
5086 #define IDX_BUFFER_BLOCK_ID		1
5087 	{STRUCT_FLD(field_name,		"BLOCK_ID"),
5088 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5089 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5090 	 STRUCT_FLD(value,		0),
5091 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5092 	 STRUCT_FLD(old_name,		""),
5093 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5094 
5095 #define IDX_BUFFER_PAGE_SPACE		2
5096 	{STRUCT_FLD(field_name,		"SPACE"),
5097 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5098 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5099 	 STRUCT_FLD(value,		0),
5100 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5101 	 STRUCT_FLD(old_name,		""),
5102 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5103 
5104 #define IDX_BUFFER_PAGE_NUM		3
5105 	{STRUCT_FLD(field_name,		"PAGE_NUMBER"),
5106 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5107 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5108 	 STRUCT_FLD(value,		0),
5109 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5110 	 STRUCT_FLD(old_name,		""),
5111 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5112 
5113 #define IDX_BUFFER_PAGE_TYPE		4
5114 	{STRUCT_FLD(field_name,		"PAGE_TYPE"),
5115 	 STRUCT_FLD(field_length,	64),
5116 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5117 	 STRUCT_FLD(value,		0),
5118 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5119 	 STRUCT_FLD(old_name,		""),
5120 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5121 
5122 #define IDX_BUFFER_PAGE_FLUSH_TYPE	5
5123 	{STRUCT_FLD(field_name,		"FLUSH_TYPE"),
5124 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5125 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5126 	 STRUCT_FLD(value,		0),
5127 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5128 	 STRUCT_FLD(old_name,		""),
5129 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5130 
5131 #define IDX_BUFFER_PAGE_FIX_COUNT	6
5132 	{STRUCT_FLD(field_name,		"FIX_COUNT"),
5133 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5134 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5135 	 STRUCT_FLD(value,		0),
5136 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5137 	 STRUCT_FLD(old_name,		""),
5138 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5139 
5140 #define IDX_BUFFER_PAGE_HASHED		7
5141 	{STRUCT_FLD(field_name,		"IS_HASHED"),
5142 	 STRUCT_FLD(field_length,	3),
5143 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5144 	 STRUCT_FLD(value,		0),
5145 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5146 	 STRUCT_FLD(old_name,		""),
5147 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5148 
5149 #define IDX_BUFFER_PAGE_NEWEST_MOD	8
5150 	{STRUCT_FLD(field_name,		"NEWEST_MODIFICATION"),
5151 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5152 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5153 	 STRUCT_FLD(value,		0),
5154 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5155 	 STRUCT_FLD(old_name,		""),
5156 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5157 
5158 #define IDX_BUFFER_PAGE_OLDEST_MOD	9
5159 	{STRUCT_FLD(field_name,		"OLDEST_MODIFICATION"),
5160 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5161 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5162 	 STRUCT_FLD(value,		0),
5163 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5164 	 STRUCT_FLD(old_name,		""),
5165 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5166 
5167 #define IDX_BUFFER_PAGE_ACCESS_TIME	10
5168 	{STRUCT_FLD(field_name,		"ACCESS_TIME"),
5169 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5170 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5171 	 STRUCT_FLD(value,		0),
5172 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5173 	 STRUCT_FLD(old_name,		""),
5174 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5175 
5176 #define IDX_BUFFER_PAGE_TABLE_NAME	11
5177 	{STRUCT_FLD(field_name,		"TABLE_NAME"),
5178 	 STRUCT_FLD(field_length,	1024),
5179 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5180 	 STRUCT_FLD(value,		0),
5181 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5182 	 STRUCT_FLD(old_name,		""),
5183 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5184 
5185 #define IDX_BUFFER_PAGE_INDEX_NAME	12
5186 	{STRUCT_FLD(field_name,		"INDEX_NAME"),
5187 	 STRUCT_FLD(field_length,	1024),
5188 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5189 	 STRUCT_FLD(value,		0),
5190 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5191 	 STRUCT_FLD(old_name,		""),
5192 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5193 
5194 #define IDX_BUFFER_PAGE_NUM_RECS	13
5195 	{STRUCT_FLD(field_name,		"NUMBER_RECORDS"),
5196 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5197 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5198 	 STRUCT_FLD(value,		0),
5199 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5200 	 STRUCT_FLD(old_name,		""),
5201 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5202 
5203 #define IDX_BUFFER_PAGE_DATA_SIZE	14
5204 	{STRUCT_FLD(field_name,		"DATA_SIZE"),
5205 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5206 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5207 	 STRUCT_FLD(value,		0),
5208 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5209 	 STRUCT_FLD(old_name,		""),
5210 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5211 
5212 #define IDX_BUFFER_PAGE_ZIP_SIZE	15
5213 	{STRUCT_FLD(field_name,		"COMPRESSED_SIZE"),
5214 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5215 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5216 	 STRUCT_FLD(value,		0),
5217 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5218 	 STRUCT_FLD(old_name,		""),
5219 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5220 
5221 #define IDX_BUFFER_PAGE_STATE		16
5222 	{STRUCT_FLD(field_name,		"PAGE_STATE"),
5223 	 STRUCT_FLD(field_length,	64),
5224 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5225 	 STRUCT_FLD(value,		0),
5226 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5227 	 STRUCT_FLD(old_name,		""),
5228 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5229 
5230 #define IDX_BUFFER_PAGE_IO_FIX		17
5231 	{STRUCT_FLD(field_name,		"IO_FIX"),
5232 	 STRUCT_FLD(field_length,	64),
5233 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5234 	 STRUCT_FLD(value,		0),
5235 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5236 	 STRUCT_FLD(old_name,		""),
5237 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5238 
5239 #define IDX_BUFFER_PAGE_IS_OLD		18
5240 	{STRUCT_FLD(field_name,		"IS_OLD"),
5241 	 STRUCT_FLD(field_length,	3),
5242 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5243 	 STRUCT_FLD(value,		0),
5244 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5245 	 STRUCT_FLD(old_name,		""),
5246 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5247 
5248 #define IDX_BUFFER_PAGE_FREE_CLOCK	19
5249 	{STRUCT_FLD(field_name,		"FREE_PAGE_CLOCK"),
5250 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5251 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5252 	 STRUCT_FLD(value,		0),
5253 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5254 	 STRUCT_FLD(old_name,		""),
5255 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5256 
5257 	END_OF_ST_FIELD_INFO
5258 };
5259 
5260 /*******************************************************************//**
5261 Fill Information Schema table INNODB_BUFFER_PAGE with information
5262 cached in the buf_page_info_t array
5263 @return 0 on success, 1 on failure */
5264 static
5265 int
i_s_innodb_buffer_page_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)5266 i_s_innodb_buffer_page_fill(
5267 /*========================*/
5268 	THD*			thd,		/*!< in: thread */
5269 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
5270 	const buf_page_info_t*	info_array,	/*!< in: array cached page
5271 						info */
5272 	ulint			num_page)	/*!< in: number of page info
5273 						cached */
5274 {
5275 	TABLE*			table;
5276 	Field**			fields;
5277 
5278 	DBUG_ENTER("i_s_innodb_buffer_page_fill");
5279 
5280 	table = tables->table;
5281 
5282 	fields = table->field;
5283 
5284 	/* Iterate through the cached array and fill the I_S table rows */
5285 	for (ulint i = 0; i < num_page; i++) {
5286 		const buf_page_info_t*	page_info;
5287 		char			table_name[MAX_FULL_NAME_LEN + 1];
5288 		const char*		table_name_end = NULL;
5289 		const char*		state_str;
5290 		enum buf_page_state	state;
5291 
5292 		page_info = info_array + i;
5293 
5294 		state_str = NULL;
5295 
5296 		OK(fields[IDX_BUFFER_POOL_ID]->store(
5297 			   page_info->pool_id, true));
5298 
5299 		OK(fields[IDX_BUFFER_BLOCK_ID]->store(
5300 			   page_info->block_id, true));
5301 
5302 		OK(fields[IDX_BUFFER_PAGE_SPACE]->store(
5303 			   page_info->space_id, true));
5304 
5305 		OK(fields[IDX_BUFFER_PAGE_NUM]->store(
5306 			   page_info->page_num, true));
5307 
5308 		OK(field_store_string(
5309 			   fields[IDX_BUFFER_PAGE_TYPE],
5310 			   i_s_page_type[page_info->page_type].type_str));
5311 
5312 		OK(fields[IDX_BUFFER_PAGE_FLUSH_TYPE]->store(
5313 			   page_info->flush_type));
5314 
5315 		OK(fields[IDX_BUFFER_PAGE_FIX_COUNT]->store(
5316 			   page_info->fix_count));
5317 
5318 		if (page_info->hashed) {
5319 			OK(field_store_string(
5320 				   fields[IDX_BUFFER_PAGE_HASHED], "YES"));
5321 		} else {
5322 			OK(field_store_string(
5323 				   fields[IDX_BUFFER_PAGE_HASHED], "NO"));
5324 		}
5325 
5326 		OK(fields[IDX_BUFFER_PAGE_NEWEST_MOD]->store(
5327 			   page_info->newest_mod, true));
5328 
5329 		OK(fields[IDX_BUFFER_PAGE_OLDEST_MOD]->store(
5330 			   page_info->oldest_mod, true));
5331 
5332 		OK(fields[IDX_BUFFER_PAGE_ACCESS_TIME]->store(
5333 			   page_info->access_time));
5334 
5335 		fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_null();
5336 
5337 		fields[IDX_BUFFER_PAGE_INDEX_NAME]->set_null();
5338 
5339 		/* If this is an index page, fetch the index name
5340 		and table name */
5341 		if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
5342 			const dict_index_t*	index;
5343 
5344 			mutex_enter(&dict_sys->mutex);
5345 			index = dict_index_get_if_in_cache_low(
5346 				page_info->index_id);
5347 
5348 			if (index) {
5349 
5350 				table_name_end = innobase_convert_name(
5351 					table_name, sizeof(table_name),
5352 					index->table_name,
5353 					strlen(index->table_name),
5354 					thd);
5355 
5356 				OK(fields[IDX_BUFFER_PAGE_TABLE_NAME]->store(
5357 					table_name,
5358 					static_cast<size_t>(table_name_end - table_name),
5359 					system_charset_info));
5360 				fields[IDX_BUFFER_PAGE_TABLE_NAME]->set_notnull();
5361 
5362 				OK(field_store_index_name(
5363 					fields[IDX_BUFFER_PAGE_INDEX_NAME],
5364 					index->name));
5365 			}
5366 
5367 			mutex_exit(&dict_sys->mutex);
5368 		}
5369 
5370 		OK(fields[IDX_BUFFER_PAGE_NUM_RECS]->store(
5371 			   page_info->num_recs, true));
5372 
5373 		OK(fields[IDX_BUFFER_PAGE_DATA_SIZE]->store(
5374 			   page_info->data_size, true));
5375 
5376 		OK(fields[IDX_BUFFER_PAGE_ZIP_SIZE]->store(
5377 			   page_info->zip_ssize
5378 			   ? (UNIV_ZIP_SIZE_MIN >> 1) << page_info->zip_ssize
5379 			   : 0, true));
5380 
5381 #if BUF_PAGE_STATE_BITS > 3
5382 # error "BUF_PAGE_STATE_BITS > 3, please ensure that all 1<<BUF_PAGE_STATE_BITS values are checked for"
5383 #endif
5384 		state = static_cast<enum buf_page_state>(page_info->page_state);
5385 
5386 		switch (state) {
5387 		/* First three states are for compression pages and
5388 		are not states we would get as we scan pages through
5389 		buffer blocks */
5390 		case BUF_BLOCK_POOL_WATCH:
5391 		case BUF_BLOCK_ZIP_PAGE:
5392 		case BUF_BLOCK_ZIP_DIRTY:
5393 			state_str = NULL;
5394 			break;
5395 		case BUF_BLOCK_NOT_USED:
5396 			state_str = "NOT_USED";
5397 			break;
5398 		case BUF_BLOCK_READY_FOR_USE:
5399 			state_str = "READY_FOR_USE";
5400 			break;
5401 		case BUF_BLOCK_FILE_PAGE:
5402 			state_str = "FILE_PAGE";
5403 			break;
5404 		case BUF_BLOCK_MEMORY:
5405 			state_str = "MEMORY";
5406 			break;
5407 		case BUF_BLOCK_REMOVE_HASH:
5408 			state_str = "REMOVE_HASH";
5409 			break;
5410 		};
5411 
5412 		OK(field_store_string(fields[IDX_BUFFER_PAGE_STATE],
5413 				      state_str));
5414 
5415 		switch (page_info->io_fix) {
5416 		case BUF_IO_NONE:
5417 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5418 					      "IO_NONE"));
5419 			break;
5420 		case BUF_IO_READ:
5421 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5422 					      "IO_READ"));
5423 			break;
5424 		case BUF_IO_WRITE:
5425 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5426 					      "IO_WRITE"));
5427 			break;
5428 		case BUF_IO_PIN:
5429 			OK(field_store_string(fields[IDX_BUFFER_PAGE_IO_FIX],
5430 					      "IO_PIN"));
5431 			break;
5432 		}
5433 
5434 		OK(field_store_string(fields[IDX_BUFFER_PAGE_IS_OLD],
5435 				      (page_info->is_old) ? "YES" : "NO"));
5436 
5437 		OK(fields[IDX_BUFFER_PAGE_FREE_CLOCK]->store(
5438 			   page_info->freed_page_clock, true));
5439 
5440 		if (schema_table_store_record(thd, table)) {
5441 			DBUG_RETURN(1);
5442 		}
5443 	}
5444 
5445 	DBUG_RETURN(0);
5446 }
5447 
5448 /*******************************************************************//**
5449 Set appropriate page type to a buf_page_info_t structure */
5450 static
5451 void
i_s_innodb_set_page_type(buf_page_info_t * page_info,ulint page_type,const byte * frame)5452 i_s_innodb_set_page_type(
5453 /*=====================*/
5454 	buf_page_info_t*page_info,	/*!< in/out: structure to fill with
5455 					scanned info */
5456 	ulint		page_type,	/*!< in: page type */
5457 	const byte*	frame)		/*!< in: buffer frame */
5458 {
5459 	if (fil_page_type_is_index(page_type)) {
5460 		const page_t*	page = (const page_t*) frame;
5461 
5462 		page_info->index_id = btr_page_get_index_id(page);
5463 
5464 		/* FIL_PAGE_INDEX and FIL_PAGE_RTREE are a bit special,
5465 		their values are defined as 17855 and 17854, so we cannot
5466 		use them to index into i_s_page_type[] array, its array index
5467 		in the i_s_page_type[] array is I_S_PAGE_TYPE_INDEX
5468 		(1) for index pages or I_S_PAGE_TYPE_IBUF for
5469 		change buffer index pages */
5470 		if (page_info->index_id
5471 		    == static_cast<index_id_t>(DICT_IBUF_ID_MIN
5472 					       + IBUF_SPACE_ID)) {
5473 			page_info->page_type = I_S_PAGE_TYPE_IBUF;
5474 		} else if (page_type == FIL_PAGE_RTREE) {
5475 			page_info->page_type = I_S_PAGE_TYPE_RTREE;
5476 		} else {
5477 			page_info->page_type = I_S_PAGE_TYPE_INDEX;
5478 		}
5479 
5480 		page_info->data_size = (ulint)(page_header_get_field(
5481 			page, PAGE_HEAP_TOP) - (page_is_comp(page)
5482 						? PAGE_NEW_SUPREMUM_END
5483 						: PAGE_OLD_SUPREMUM_END)
5484 			- page_header_get_field(page, PAGE_GARBAGE));
5485 
5486 		page_info->num_recs = page_get_n_recs(page);
5487 	} else if (page_type > FIL_PAGE_TYPE_LAST) {
5488 		/* Encountered an unknown page type */
5489 		page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5490 	} else {
5491 		/* Make sure we get the right index into the
5492 		i_s_page_type[] array */
5493 		ut_a(page_type == i_s_page_type[page_type].type_value);
5494 
5495 		page_info->page_type = page_type;
5496 	}
5497 
5498 	if (page_info->page_type == FIL_PAGE_TYPE_ZBLOB
5499 	    || page_info->page_type == FIL_PAGE_TYPE_ZBLOB2) {
5500 		page_info->page_num = mach_read_from_4(
5501 			frame + FIL_PAGE_OFFSET);
5502 		page_info->space_id = mach_read_from_4(
5503 			frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
5504 	}
5505 }
5506 /*******************************************************************//**
5507 Scans pages in the buffer cache, and collect their general information
5508 into the buf_page_info_t array which is zero-filled. So any fields
5509 that are not initialized in the function will default to 0 */
5510 static
5511 void
i_s_innodb_buffer_page_get_info(const buf_page_t * bpage,ulint pool_id,ulint pos,buf_page_info_t * page_info)5512 i_s_innodb_buffer_page_get_info(
5513 /*============================*/
5514 	const buf_page_t*bpage,		/*!< in: buffer pool page to scan */
5515 	ulint		pool_id,	/*!< in: buffer pool id */
5516 	ulint		pos,		/*!< in: buffer block position in
5517 					buffer pool or in the LRU list */
5518 	buf_page_info_t*page_info)	/*!< in: zero filled info structure;
5519 					out: structure filled with scanned
5520 					info */
5521 {
5522 	ut_ad(pool_id < MAX_BUFFER_POOLS);
5523 
5524 	page_info->pool_id = pool_id;
5525 
5526 	page_info->block_id = pos;
5527 
5528 	page_info->page_state = buf_page_get_state(bpage);
5529 
5530 	/* Only fetch information for buffers that map to a tablespace,
5531 	that is, buffer page with state BUF_BLOCK_ZIP_PAGE,
5532 	BUF_BLOCK_ZIP_DIRTY or BUF_BLOCK_FILE_PAGE */
5533 	if (buf_page_in_file(bpage)) {
5534 		const byte*	frame;
5535 		ulint		page_type;
5536 
5537 		page_info->space_id = bpage->id.space();
5538 
5539 		page_info->page_num = bpage->id.page_no();
5540 
5541 		page_info->flush_type = bpage->flush_type;
5542 
5543 		page_info->fix_count = bpage->buf_fix_count;
5544 
5545 		page_info->newest_mod = bpage->newest_modification;
5546 
5547 		page_info->oldest_mod = bpage->oldest_modification;
5548 
5549 		page_info->access_time = bpage->access_time;
5550 
5551 		page_info->zip_ssize = bpage->zip.ssize;
5552 
5553 		page_info->io_fix = bpage->io_fix;
5554 
5555 		page_info->is_old = bpage->old;
5556 
5557 		page_info->freed_page_clock = bpage->freed_page_clock;
5558 
5559 		switch (buf_page_get_io_fix(bpage)) {
5560 		case BUF_IO_NONE:
5561 		case BUF_IO_WRITE:
5562 		case BUF_IO_PIN:
5563 			break;
5564 		case BUF_IO_READ:
5565 			page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5566 			return;
5567 		}
5568 
5569 		if (page_info->page_state == BUF_BLOCK_FILE_PAGE) {
5570 			const buf_block_t*block;
5571 
5572 			block = reinterpret_cast<const buf_block_t*>(bpage);
5573 			frame = block->frame;
5574 			/* Note: this may be a false positive, that
5575 			is, block->index will not always be set to
5576 			NULL when the last adaptive hash index
5577 			reference is dropped. */
5578 			page_info->hashed = (block->index != NULL);
5579 		} else {
5580 			ut_ad(page_info->zip_ssize);
5581 			frame = bpage->zip.data;
5582 		}
5583 
5584 		page_type = fil_page_get_type(frame);
5585 
5586 		i_s_innodb_set_page_type(page_info, page_type, frame);
5587 	} else {
5588 		page_info->page_type = I_S_PAGE_TYPE_UNKNOWN;
5589 	}
5590 }
5591 
5592 /*******************************************************************//**
5593 This is the function that goes through each block of the buffer pool
5594 and fetch information to information schema tables: INNODB_BUFFER_PAGE.
5595 @return 0 on success, 1 on failure */
5596 static
5597 int
i_s_innodb_fill_buffer_pool(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)5598 i_s_innodb_fill_buffer_pool(
5599 /*========================*/
5600 	THD*			thd,		/*!< in: thread */
5601 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
5602 	buf_pool_t*		buf_pool,	/*!< in: buffer pool to scan */
5603 	const ulint		pool_id)	/*!< in: buffer pool id */
5604 {
5605 	int			status	= 0;
5606 	mem_heap_t*		heap;
5607 
5608 	DBUG_ENTER("i_s_innodb_fill_buffer_pool");
5609 
5610 	heap = mem_heap_create(10000);
5611 
5612 	/* Go through each chunk of buffer pool. Currently, we only
5613 	have one single chunk for each buffer pool */
5614 	for (ulint n = 0;
5615 	     n < ut_min(buf_pool->n_chunks, buf_pool->n_chunks_new); n++) {
5616 		const buf_block_t*	block;
5617 		ulint			n_blocks;
5618 		buf_page_info_t*	info_buffer;
5619 		ulint			num_page;
5620 		ulint			mem_size;
5621 		ulint			chunk_size;
5622 		ulint			num_to_process = 0;
5623 		ulint			block_id = 0;
5624 
5625 		/* Get buffer block of the nth chunk */
5626 		block = buf_get_nth_chunk_block(buf_pool, n, &chunk_size);
5627 		num_page = 0;
5628 
5629 		while (chunk_size > 0) {
5630 			/* we cache maximum MAX_BUF_INFO_CACHED number of
5631 			buffer page info */
5632 			num_to_process = ut_min(chunk_size,
5633 						MAX_BUF_INFO_CACHED);
5634 
5635 			mem_size = num_to_process * sizeof(buf_page_info_t);
5636 
5637 			/* For each chunk, we'll pre-allocate information
5638 			structures to cache the page information read from
5639 			the buffer pool. Doing so before obtain any mutex */
5640 			info_buffer = (buf_page_info_t*) mem_heap_zalloc(
5641 				heap, mem_size);
5642 
5643 			/* Obtain appropriate mutexes. Since this is diagnostic
5644 			buffer pool info printout, we are not required to
5645 			preserve the overall consistency, so we can
5646 			release mutex periodically */
5647 			buf_pool_mutex_enter(buf_pool);
5648 
5649 			/* GO through each block in the chunk */
5650 			for (n_blocks = num_to_process; n_blocks--; block++) {
5651 				i_s_innodb_buffer_page_get_info(
5652 					&block->page, pool_id, block_id,
5653 					info_buffer + num_page);
5654 				block_id++;
5655 				num_page++;
5656 			}
5657 
5658 			buf_pool_mutex_exit(buf_pool);
5659 
5660 			/* Fill in information schema table with information
5661 			just collected from the buffer chunk scan */
5662 			status = i_s_innodb_buffer_page_fill(
5663 				thd, tables, info_buffer,
5664 				num_page);
5665 
5666 			/* If something goes wrong, break and return */
5667 			if (status) {
5668 				break;
5669 			}
5670 
5671 			mem_heap_empty(heap);
5672 			chunk_size -= num_to_process;
5673 			num_page = 0;
5674 		}
5675 	}
5676 
5677 	mem_heap_free(heap);
5678 
5679 	DBUG_RETURN(status);
5680 }
5681 
5682 /*******************************************************************//**
5683 Fill page information for pages in InnoDB buffer pool to the
5684 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
5685 @return 0 on success, 1 on failure */
5686 static
5687 int
i_s_innodb_buffer_page_fill_table(THD * thd,TABLE_LIST * tables,Item *)5688 i_s_innodb_buffer_page_fill_table(
5689 /*==============================*/
5690 	THD*		thd,		/*!< in: thread */
5691 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
5692 	Item*		)		/*!< in: condition (ignored) */
5693 {
5694 	int	status	= 0;
5695 
5696 	DBUG_ENTER("i_s_innodb_buffer_page_fill_table");
5697 
5698 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
5699 
5700 	/* deny access to user without PROCESS privilege */
5701 	if (check_global_access(thd, PROCESS_ACL)) {
5702 		DBUG_RETURN(0);
5703 	}
5704 
5705 	/* Walk through each buffer pool */
5706 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
5707 		buf_pool_t*	buf_pool;
5708 
5709 		buf_pool = buf_pool_from_array(i);
5710 
5711 		/* Fetch information from pages in this buffer pool,
5712 		and fill the corresponding I_S table */
5713 		status = i_s_innodb_fill_buffer_pool(thd, tables, buf_pool, i);
5714 
5715 		/* If something wrong, break and return */
5716 		if (status) {
5717 			break;
5718 		}
5719 	}
5720 
5721 	DBUG_RETURN(status);
5722 }
5723 
5724 /*******************************************************************//**
5725 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE.
5726 @return 0 on success, 1 on failure */
5727 static
5728 int
i_s_innodb_buffer_page_init(void * p)5729 i_s_innodb_buffer_page_init(
5730 /*========================*/
5731 	void*	p)	/*!< in/out: table schema object */
5732 {
5733 	ST_SCHEMA_TABLE*	schema;
5734 
5735 	DBUG_ENTER("i_s_innodb_buffer_page_init");
5736 
5737 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
5738 
5739 	schema->fields_info = i_s_innodb_buffer_page_fields_info;
5740 	schema->fill_table = i_s_innodb_buffer_page_fill_table;
5741 
5742 	DBUG_RETURN(0);
5743 }
5744 
5745 struct st_mysql_plugin	i_s_innodb_buffer_page =
5746 {
5747 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
5748 	/* int */
5749 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
5750 
5751 	/* pointer to type-specific plugin descriptor */
5752 	/* void* */
5753 	STRUCT_FLD(info, &i_s_info),
5754 
5755 	/* plugin name */
5756 	/* const char* */
5757 	STRUCT_FLD(name, "INNODB_BUFFER_PAGE"),
5758 
5759 	/* plugin author (for SHOW PLUGINS) */
5760 	/* const char* */
5761 	STRUCT_FLD(author, plugin_author),
5762 
5763 	/* general descriptive text (for SHOW PLUGINS) */
5764 	/* const char* */
5765 	STRUCT_FLD(descr, "InnoDB Buffer Page Information"),
5766 
5767 	/* the plugin license (PLUGIN_LICENSE_XXX) */
5768 	/* int */
5769 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
5770 
5771 	/* the function to invoke when plugin is loaded */
5772 	/* int (*)(void*); */
5773 	STRUCT_FLD(init, i_s_innodb_buffer_page_init),
5774 
5775 	/* the function to invoke when plugin is unloaded */
5776 	/* int (*)(void*); */
5777 	STRUCT_FLD(deinit, i_s_common_deinit),
5778 
5779 	/* plugin version (for SHOW PLUGINS) */
5780 	/* unsigned int */
5781 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
5782 
5783 	/* struct st_mysql_show_var* */
5784 	STRUCT_FLD(status_vars, NULL),
5785 
5786 	/* struct st_mysql_sys_var** */
5787 	STRUCT_FLD(system_vars, NULL),
5788 
5789 	/* reserved for dependency checking */
5790 	/* void* */
5791 	STRUCT_FLD(__reserved1, NULL),
5792 
5793 	/* Plugin flags */
5794 	/* unsigned long */
5795 	STRUCT_FLD(flags, 0UL),
5796 };
5797 
5798 static ST_FIELD_INFO	i_s_innodb_buf_page_lru_fields_info[] =
5799 {
5800 #define IDX_BUF_LRU_POOL_ID		0
5801 	{STRUCT_FLD(field_name,		"POOL_ID"),
5802 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5803 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5804 	 STRUCT_FLD(value,		0),
5805 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5806 	 STRUCT_FLD(old_name,		""),
5807 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5808 
5809 #define IDX_BUF_LRU_POS			1
5810 	{STRUCT_FLD(field_name,		"LRU_POSITION"),
5811 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5812 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5813 	 STRUCT_FLD(value,		0),
5814 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5815 	 STRUCT_FLD(old_name,		""),
5816 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5817 
5818 #define IDX_BUF_LRU_PAGE_SPACE		2
5819 	{STRUCT_FLD(field_name,		"SPACE"),
5820 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5821 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5822 	 STRUCT_FLD(value,		0),
5823 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5824 	 STRUCT_FLD(old_name,		""),
5825 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5826 
5827 #define IDX_BUF_LRU_PAGE_NUM		3
5828 	{STRUCT_FLD(field_name,		"PAGE_NUMBER"),
5829 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5830 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5831 	 STRUCT_FLD(value,		0),
5832 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5833 	 STRUCT_FLD(old_name,		""),
5834 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5835 
5836 #define IDX_BUF_LRU_PAGE_TYPE		4
5837 	{STRUCT_FLD(field_name,		"PAGE_TYPE"),
5838 	 STRUCT_FLD(field_length,	64),
5839 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5840 	 STRUCT_FLD(value,		0),
5841 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5842 	 STRUCT_FLD(old_name,		""),
5843 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5844 
5845 #define IDX_BUF_LRU_PAGE_FLUSH_TYPE	5
5846 	{STRUCT_FLD(field_name,		"FLUSH_TYPE"),
5847 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5848 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5849 	 STRUCT_FLD(value,		0),
5850 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5851 	 STRUCT_FLD(old_name,		""),
5852 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5853 
5854 #define IDX_BUF_LRU_PAGE_FIX_COUNT	6
5855 	{STRUCT_FLD(field_name,		"FIX_COUNT"),
5856 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5857 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5858 	 STRUCT_FLD(value,		0),
5859 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5860 	 STRUCT_FLD(old_name,		""),
5861 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5862 
5863 #define IDX_BUF_LRU_PAGE_HASHED		7
5864 	{STRUCT_FLD(field_name,		"IS_HASHED"),
5865 	 STRUCT_FLD(field_length,	3),
5866 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5867 	 STRUCT_FLD(value,		0),
5868 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5869 	 STRUCT_FLD(old_name,		""),
5870 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5871 
5872 #define IDX_BUF_LRU_PAGE_NEWEST_MOD	8
5873 	{STRUCT_FLD(field_name,		"NEWEST_MODIFICATION"),
5874 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5875 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5876 	 STRUCT_FLD(value,		0),
5877 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5878 	 STRUCT_FLD(old_name,		""),
5879 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5880 
5881 #define IDX_BUF_LRU_PAGE_OLDEST_MOD	9
5882 	{STRUCT_FLD(field_name,		"OLDEST_MODIFICATION"),
5883 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5884 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5885 	 STRUCT_FLD(value,		0),
5886 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5887 	 STRUCT_FLD(old_name,		""),
5888 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5889 
5890 #define IDX_BUF_LRU_PAGE_ACCESS_TIME	10
5891 	{STRUCT_FLD(field_name,		"ACCESS_TIME"),
5892 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5893 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5894 	 STRUCT_FLD(value,		0),
5895 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5896 	 STRUCT_FLD(old_name,		""),
5897 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5898 
5899 #define IDX_BUF_LRU_PAGE_TABLE_NAME	11
5900 	{STRUCT_FLD(field_name,		"TABLE_NAME"),
5901 	 STRUCT_FLD(field_length,	1024),
5902 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5903 	 STRUCT_FLD(value,		0),
5904 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5905 	 STRUCT_FLD(old_name,		""),
5906 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5907 
5908 #define IDX_BUF_LRU_PAGE_INDEX_NAME	12
5909 	{STRUCT_FLD(field_name,		"INDEX_NAME"),
5910 	 STRUCT_FLD(field_length,	1024),
5911 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5912 	 STRUCT_FLD(value,		0),
5913 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5914 	 STRUCT_FLD(old_name,		""),
5915 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5916 
5917 #define IDX_BUF_LRU_PAGE_NUM_RECS	13
5918 	{STRUCT_FLD(field_name,		"NUMBER_RECORDS"),
5919 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5920 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5921 	 STRUCT_FLD(value,		0),
5922 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5923 	 STRUCT_FLD(old_name,		""),
5924 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5925 
5926 #define IDX_BUF_LRU_PAGE_DATA_SIZE	14
5927 	{STRUCT_FLD(field_name,		"DATA_SIZE"),
5928 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5929 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5930 	 STRUCT_FLD(value,		0),
5931 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5932 	 STRUCT_FLD(old_name,		""),
5933 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5934 
5935 #define IDX_BUF_LRU_PAGE_ZIP_SIZE	15
5936 	{STRUCT_FLD(field_name,		"COMPRESSED_SIZE"),
5937 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5938 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5939 	 STRUCT_FLD(value,		0),
5940 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5941 	 STRUCT_FLD(old_name,		""),
5942 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5943 
5944 #define IDX_BUF_LRU_PAGE_STATE		16
5945 	{STRUCT_FLD(field_name,		"COMPRESSED"),
5946 	 STRUCT_FLD(field_length,	3),
5947 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5948 	 STRUCT_FLD(value,		0),
5949 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5950 	 STRUCT_FLD(old_name,		""),
5951 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5952 
5953 #define IDX_BUF_LRU_PAGE_IO_FIX		17
5954 	{STRUCT_FLD(field_name,		"IO_FIX"),
5955 	 STRUCT_FLD(field_length,	64),
5956 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5957 	 STRUCT_FLD(value,		0),
5958 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5959 	 STRUCT_FLD(old_name,		""),
5960 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5961 
5962 #define IDX_BUF_LRU_PAGE_IS_OLD		18
5963 	{STRUCT_FLD(field_name,		"IS_OLD"),
5964 	 STRUCT_FLD(field_length,	3),
5965 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
5966 	 STRUCT_FLD(value,		0),
5967 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
5968 	 STRUCT_FLD(old_name,		""),
5969 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5970 
5971 #define IDX_BUF_LRU_PAGE_FREE_CLOCK	19
5972 	{STRUCT_FLD(field_name,		"FREE_PAGE_CLOCK"),
5973 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
5974 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
5975 	 STRUCT_FLD(value,		0),
5976 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
5977 	 STRUCT_FLD(old_name,		""),
5978 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
5979 
5980 	END_OF_ST_FIELD_INFO
5981 };
5982 
5983 /*******************************************************************//**
5984 Fill Information Schema table INNODB_BUFFER_PAGE_LRU with information
5985 cached in the buf_page_info_t array
5986 @return 0 on success, 1 on failure */
5987 static
5988 int
i_s_innodb_buf_page_lru_fill(THD * thd,TABLE_LIST * tables,const buf_page_info_t * info_array,ulint num_page)5989 i_s_innodb_buf_page_lru_fill(
5990 /*=========================*/
5991 	THD*			thd,		/*!< in: thread */
5992 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
5993 	const buf_page_info_t*	info_array,	/*!< in: array cached page
5994 						info */
5995 	ulint			num_page)	/*!< in: number of page info
5996 						 cached */
5997 {
5998 	TABLE*			table;
5999 	Field**			fields;
6000 	mem_heap_t*		heap;
6001 
6002 	DBUG_ENTER("i_s_innodb_buf_page_lru_fill");
6003 
6004 	table = tables->table;
6005 
6006 	fields = table->field;
6007 
6008 	heap = mem_heap_create(1000);
6009 
6010 	/* Iterate through the cached array and fill the I_S table rows */
6011 	for (ulint i = 0; i < num_page; i++) {
6012 		const buf_page_info_t*	page_info;
6013 		char			table_name[MAX_FULL_NAME_LEN + 1];
6014 		const char*		table_name_end = NULL;
6015 		const char*		state_str;
6016 		enum buf_page_state	state;
6017 
6018 		state_str = NULL;
6019 
6020 		page_info = info_array + i;
6021 
6022 		OK(fields[IDX_BUF_LRU_POOL_ID]->store(
6023 			   page_info->pool_id, true));
6024 
6025 		OK(fields[IDX_BUF_LRU_POS]->store(
6026 			   page_info->block_id, true));
6027 
6028 		OK(fields[IDX_BUF_LRU_PAGE_SPACE]->store(
6029 			   page_info->space_id, true));
6030 
6031 		OK(fields[IDX_BUF_LRU_PAGE_NUM]->store(
6032 			   page_info->page_num, true));
6033 
6034 		OK(field_store_string(
6035 			   fields[IDX_BUF_LRU_PAGE_TYPE],
6036 			   i_s_page_type[page_info->page_type].type_str));
6037 
6038 		OK(fields[IDX_BUF_LRU_PAGE_FLUSH_TYPE]->store(
6039 			   page_info->flush_type, true));
6040 
6041 		OK(fields[IDX_BUF_LRU_PAGE_FIX_COUNT]->store(
6042 			   page_info->fix_count, true));
6043 
6044 		if (page_info->hashed) {
6045 			OK(field_store_string(
6046 				   fields[IDX_BUF_LRU_PAGE_HASHED], "YES"));
6047 		} else {
6048 			OK(field_store_string(
6049 				   fields[IDX_BUF_LRU_PAGE_HASHED], "NO"));
6050 		}
6051 
6052 		OK(fields[IDX_BUF_LRU_PAGE_NEWEST_MOD]->store(
6053 			   page_info->newest_mod, true));
6054 
6055 		OK(fields[IDX_BUF_LRU_PAGE_OLDEST_MOD]->store(
6056 			   page_info->oldest_mod, true));
6057 
6058 		OK(fields[IDX_BUF_LRU_PAGE_ACCESS_TIME]->store(
6059 			   page_info->access_time, true));
6060 
6061 		fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_null();
6062 
6063 		fields[IDX_BUF_LRU_PAGE_INDEX_NAME]->set_null();
6064 
6065 		/* If this is an index page, fetch the index name
6066 		and table name */
6067 		if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
6068 			const dict_index_t*	index;
6069 
6070 			mutex_enter(&dict_sys->mutex);
6071 			index = dict_index_get_if_in_cache_low(
6072 				page_info->index_id);
6073 
6074 			if (index) {
6075 
6076 				table_name_end = innobase_convert_name(
6077 					table_name, sizeof(table_name),
6078 					index->table_name,
6079 					strlen(index->table_name),
6080 					thd);
6081 
6082 				OK(fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->store(
6083 					table_name,
6084 					static_cast<size_t>(table_name_end - table_name),
6085 					system_charset_info));
6086 				fields[IDX_BUF_LRU_PAGE_TABLE_NAME]->set_notnull();
6087 
6088 				OK(field_store_index_name(
6089 					fields[IDX_BUF_LRU_PAGE_INDEX_NAME],
6090 					index->name));
6091 			}
6092 
6093 			mutex_exit(&dict_sys->mutex);
6094 		}
6095 
6096 		OK(fields[IDX_BUF_LRU_PAGE_NUM_RECS]->store(
6097 			   page_info->num_recs, true));
6098 
6099 		OK(fields[IDX_BUF_LRU_PAGE_DATA_SIZE]->store(
6100 			   page_info->data_size, true));
6101 
6102 		OK(fields[IDX_BUF_LRU_PAGE_ZIP_SIZE]->store(
6103 			   page_info->zip_ssize ?
6104 			   512 << page_info->zip_ssize : 0, true));
6105 
6106 		state = static_cast<enum buf_page_state>(page_info->page_state);
6107 
6108 		switch (state) {
6109 		/* Compressed page */
6110 		case BUF_BLOCK_ZIP_PAGE:
6111 		case BUF_BLOCK_ZIP_DIRTY:
6112 			state_str = "YES";
6113 			break;
6114 		/* Uncompressed page */
6115 		case BUF_BLOCK_FILE_PAGE:
6116 			state_str = "NO";
6117 			break;
6118 		/* We should not see following states */
6119 		case BUF_BLOCK_POOL_WATCH:
6120 		case BUF_BLOCK_READY_FOR_USE:
6121 		case BUF_BLOCK_NOT_USED:
6122 		case BUF_BLOCK_MEMORY:
6123 		case BUF_BLOCK_REMOVE_HASH:
6124 			state_str = NULL;
6125 			break;
6126 		};
6127 
6128 		OK(field_store_string(fields[IDX_BUF_LRU_PAGE_STATE],
6129 				      state_str));
6130 
6131 		switch (page_info->io_fix) {
6132 		case BUF_IO_NONE:
6133 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
6134 					      "IO_NONE"));
6135 			break;
6136 		case BUF_IO_READ:
6137 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
6138 					      "IO_READ"));
6139 			break;
6140 		case BUF_IO_WRITE:
6141 			OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IO_FIX],
6142 					      "IO_WRITE"));
6143 			break;
6144 		}
6145 
6146 		OK(field_store_string(fields[IDX_BUF_LRU_PAGE_IS_OLD],
6147 				      (page_info->is_old) ? "YES" : "NO"));
6148 
6149 		OK(fields[IDX_BUF_LRU_PAGE_FREE_CLOCK]->store(
6150 			   page_info->freed_page_clock, true));
6151 
6152 		if (schema_table_store_record(thd, table)) {
6153 			mem_heap_free(heap);
6154 			DBUG_RETURN(1);
6155 		}
6156 
6157 		mem_heap_empty(heap);
6158 	}
6159 
6160 	mem_heap_free(heap);
6161 
6162 	DBUG_RETURN(0);
6163 }
6164 
6165 /*******************************************************************//**
6166 This is the function that goes through buffer pool's LRU list
6167 and fetch information to INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
6168 @return 0 on success, 1 on failure */
6169 static
6170 int
i_s_innodb_fill_buffer_lru(THD * thd,TABLE_LIST * tables,buf_pool_t * buf_pool,const ulint pool_id)6171 i_s_innodb_fill_buffer_lru(
6172 /*=======================*/
6173 	THD*			thd,		/*!< in: thread */
6174 	TABLE_LIST*		tables,		/*!< in/out: tables to fill */
6175 	buf_pool_t*		buf_pool,	/*!< in: buffer pool to scan */
6176 	const ulint		pool_id)	/*!< in: buffer pool id */
6177 {
6178 	int			status = 0;
6179 	buf_page_info_t*	info_buffer;
6180 	ulint			lru_pos = 0;
6181 	const buf_page_t*	bpage;
6182 	ulint			lru_len;
6183 
6184 	DBUG_ENTER("i_s_innodb_fill_buffer_lru");
6185 
6186 	/* Obtain buf_pool mutex before allocate info_buffer, since
6187 	UT_LIST_GET_LEN(buf_pool->LRU) could change */
6188 	buf_pool_mutex_enter(buf_pool);
6189 
6190 	lru_len = UT_LIST_GET_LEN(buf_pool->LRU);
6191 
6192 	/* Print error message if malloc fail */
6193 	info_buffer = (buf_page_info_t*) my_malloc(PSI_INSTRUMENT_ME,
6194 		lru_len * sizeof *info_buffer, MYF(MY_WME));
6195 
6196 	if (!info_buffer) {
6197 		status = 1;
6198 		goto exit;
6199 	}
6200 
6201 	memset(info_buffer, 0, lru_len * sizeof *info_buffer);
6202 
6203 	/* Walk through Pool's LRU list and print the buffer page
6204 	information */
6205 	bpage = UT_LIST_GET_LAST(buf_pool->LRU);
6206 
6207 	while (bpage != NULL) {
6208 		/* Use the same function that collect buffer info for
6209 		INNODB_BUFFER_PAGE to get buffer page info */
6210 		i_s_innodb_buffer_page_get_info(bpage, pool_id, lru_pos,
6211 						(info_buffer + lru_pos));
6212 
6213 		bpage = UT_LIST_GET_PREV(LRU, bpage);
6214 
6215 		lru_pos++;
6216 	}
6217 
6218 	ut_ad(lru_pos == lru_len);
6219 	ut_ad(lru_pos == UT_LIST_GET_LEN(buf_pool->LRU));
6220 
6221 exit:
6222 	buf_pool_mutex_exit(buf_pool);
6223 
6224 	if (info_buffer) {
6225 		status = i_s_innodb_buf_page_lru_fill(
6226 			thd, tables, info_buffer, lru_len);
6227 
6228 		my_free(info_buffer);
6229 	}
6230 
6231 	DBUG_RETURN(status);
6232 }
6233 
6234 /*******************************************************************//**
6235 Fill page information for pages in InnoDB buffer pool to the
6236 dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU
6237 @return 0 on success, 1 on failure */
6238 static
6239 int
i_s_innodb_buf_page_lru_fill_table(THD * thd,TABLE_LIST * tables,Item *)6240 i_s_innodb_buf_page_lru_fill_table(
6241 /*===============================*/
6242 	THD*		thd,		/*!< in: thread */
6243 	TABLE_LIST*	tables,		/*!< in/out: tables to fill */
6244 	Item*		)		/*!< in: condition (ignored) */
6245 {
6246 	int	status	= 0;
6247 
6248 	DBUG_ENTER("i_s_innodb_buf_page_lru_fill_table");
6249 
6250 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6251 
6252 	/* deny access to any users that do not hold PROCESS_ACL */
6253 	if (check_global_access(thd, PROCESS_ACL)) {
6254 		DBUG_RETURN(0);
6255 	}
6256 
6257 	/* Walk through each buffer pool */
6258 	for (ulint i = 0; i < srv_buf_pool_instances; i++) {
6259 		buf_pool_t*	buf_pool;
6260 
6261 		buf_pool = buf_pool_from_array(i);
6262 
6263 		/* Fetch information from pages in this buffer pool's LRU list,
6264 		and fill the corresponding I_S table */
6265 		status = i_s_innodb_fill_buffer_lru(thd, tables, buf_pool, i);
6266 
6267 		/* If something wrong, break and return */
6268 		if (status) {
6269 			break;
6270 		}
6271 	}
6272 
6273 	DBUG_RETURN(status);
6274 }
6275 
6276 /*******************************************************************//**
6277 Bind the dynamic table INFORMATION_SCHEMA.INNODB_BUFFER_PAGE_LRU.
6278 @return 0 on success, 1 on failure */
6279 static
6280 int
i_s_innodb_buffer_page_lru_init(void * p)6281 i_s_innodb_buffer_page_lru_init(
6282 /*============================*/
6283 	void*	p)	/*!< in/out: table schema object */
6284 {
6285 	ST_SCHEMA_TABLE*	schema;
6286 
6287 	DBUG_ENTER("i_s_innodb_buffer_page_lru_init");
6288 
6289 	schema = reinterpret_cast<ST_SCHEMA_TABLE*>(p);
6290 
6291 	schema->fields_info = i_s_innodb_buf_page_lru_fields_info;
6292 	schema->fill_table = i_s_innodb_buf_page_lru_fill_table;
6293 
6294 	DBUG_RETURN(0);
6295 }
6296 
6297 struct st_mysql_plugin	i_s_innodb_buffer_page_lru =
6298 {
6299 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
6300 	/* int */
6301 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6302 
6303 	/* pointer to type-specific plugin descriptor */
6304 	/* void* */
6305 	STRUCT_FLD(info, &i_s_info),
6306 
6307 	/* plugin name */
6308 	/* const char* */
6309 	STRUCT_FLD(name, "INNODB_BUFFER_PAGE_LRU"),
6310 
6311 	/* plugin author (for SHOW PLUGINS) */
6312 	/* const char* */
6313 	STRUCT_FLD(author, plugin_author),
6314 
6315 	/* general descriptive text (for SHOW PLUGINS) */
6316 	/* const char* */
6317 	STRUCT_FLD(descr, "InnoDB Buffer Page in LRU"),
6318 
6319 	/* the plugin license (PLUGIN_LICENSE_XXX) */
6320 	/* int */
6321 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6322 
6323 	/* the function to invoke when plugin is loaded */
6324 	/* int (*)(void*); */
6325 	STRUCT_FLD(init, i_s_innodb_buffer_page_lru_init),
6326 
6327 	/* the function to invoke when plugin is unloaded */
6328 	/* int (*)(void*); */
6329 	STRUCT_FLD(deinit, i_s_common_deinit),
6330 
6331 	/* plugin version (for SHOW PLUGINS) */
6332 	/* unsigned int */
6333 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
6334 
6335 	/* struct st_mysql_show_var* */
6336 	STRUCT_FLD(status_vars, NULL),
6337 
6338 	/* struct st_mysql_sys_var** */
6339 	STRUCT_FLD(system_vars, NULL),
6340 
6341 	/* reserved for dependency checking */
6342 	/* void* */
6343 	STRUCT_FLD(__reserved1, NULL),
6344 
6345 	/* Plugin flags */
6346 	/* unsigned long */
6347 	STRUCT_FLD(flags, 0UL),
6348 };
6349 
6350 /*******************************************************************//**
6351 Unbind a dynamic INFORMATION_SCHEMA table.
6352 @return 0 on success */
6353 static
6354 int
i_s_common_deinit(void * p)6355 i_s_common_deinit(
6356 /*==============*/
6357 	void*	p)	/*!< in/out: table schema object */
6358 {
6359 	DBUG_ENTER("i_s_common_deinit");
6360 
6361 	/* Do nothing */
6362 
6363 	DBUG_RETURN(0);
6364 }
6365 
6366 /**  SYS_TABLES  ***************************************************/
6367 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLES */
6368 static ST_FIELD_INFO	innodb_sys_tables_fields_info[] =
6369 {
6370 #define SYS_TABLES_ID			0
6371 	{STRUCT_FLD(field_name,		"TABLE_ID"),
6372 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6373 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6374 	 STRUCT_FLD(value,		0),
6375 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6376 	 STRUCT_FLD(old_name,		""),
6377 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6378 
6379 #define SYS_TABLES_NAME			1
6380 	{STRUCT_FLD(field_name,		"NAME"),
6381 	 STRUCT_FLD(field_length,	MAX_FULL_NAME_LEN + 1),
6382 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6383 	 STRUCT_FLD(value,		0),
6384 	 STRUCT_FLD(field_flags,	0),
6385 	 STRUCT_FLD(old_name,		""),
6386 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6387 
6388 #define SYS_TABLES_FLAG			2
6389 	{STRUCT_FLD(field_name,		"FLAG"),
6390 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6391 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6392 	 STRUCT_FLD(value,		0),
6393 	 STRUCT_FLD(field_flags,	0),
6394 	 STRUCT_FLD(old_name,		""),
6395 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6396 
6397 #define SYS_TABLES_NUM_COLUMN		3
6398 	{STRUCT_FLD(field_name,		"N_COLS"),
6399 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6400 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6401 	 STRUCT_FLD(value,		0),
6402 	 STRUCT_FLD(field_flags,	0),
6403 	 STRUCT_FLD(old_name,		""),
6404 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6405 
6406 #define SYS_TABLES_SPACE		4
6407 	{STRUCT_FLD(field_name,		"SPACE"),
6408 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6409 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6410 	 STRUCT_FLD(value,		0),
6411 	 STRUCT_FLD(field_flags,	0),
6412 	 STRUCT_FLD(old_name,		""),
6413 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6414 
6415 #define SYS_TABLES_FILE_FORMAT		5
6416 	{STRUCT_FLD(field_name,		"FILE_FORMAT"),
6417 	 STRUCT_FLD(field_length,	10),
6418 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6419 	 STRUCT_FLD(value,		0),
6420 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
6421 	 STRUCT_FLD(old_name,		""),
6422 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6423 
6424 #define SYS_TABLES_ROW_FORMAT		6
6425 	{STRUCT_FLD(field_name,		"ROW_FORMAT"),
6426 	 STRUCT_FLD(field_length,	12),
6427 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6428 	 STRUCT_FLD(value,		0),
6429 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
6430 	 STRUCT_FLD(old_name,		""),
6431 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6432 
6433 #define SYS_TABLES_ZIP_PAGE_SIZE	7
6434 	{STRUCT_FLD(field_name,		"ZIP_PAGE_SIZE"),
6435 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6436 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6437 	 STRUCT_FLD(value,		0),
6438 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6439 	 STRUCT_FLD(old_name,		""),
6440 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6441 
6442 #define SYS_TABLES_SPACE_TYPE	8
6443 	{STRUCT_FLD(field_name,		"SPACE_TYPE"),
6444 	 STRUCT_FLD(field_length,	10),
6445 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6446 	 STRUCT_FLD(value,		0),
6447 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
6448 	 STRUCT_FLD(old_name,		""),
6449 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6450 
6451 	END_OF_ST_FIELD_INFO
6452 };
6453 
6454 /**********************************************************************//**
6455 Populate information_schema.innodb_sys_tables table with information
6456 from SYS_TABLES.
6457 @return 0 on success */
6458 static
6459 int
i_s_dict_fill_sys_tables(THD * thd,dict_table_t * table,TABLE * table_to_fill)6460 i_s_dict_fill_sys_tables(
6461 /*=====================*/
6462 	THD*		thd,		/*!< in: thread */
6463 	dict_table_t*	table,		/*!< in: table */
6464 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
6465 {
6466 	Field**			fields;
6467 	ulint			compact = DICT_TF_GET_COMPACT(table->flags);
6468 	ulint			atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(
6469 								table->flags);
6470 	const page_size_t&	page_size = dict_tf_get_page_size(table->flags);
6471 	const char*		file_format;
6472 	const char*		row_format;
6473 	const char*		space_type;
6474 
6475 	file_format = trx_sys_file_format_id_to_name(atomic_blobs);
6476 	if (!compact) {
6477 		row_format = "Redundant";
6478 	} else if (!atomic_blobs) {
6479 		row_format = "Compact";
6480 	} else if (DICT_TF_GET_ZIP_SSIZE(table->flags)) {
6481 		row_format = "Compressed";
6482 	} else {
6483 		row_format = "Dynamic";
6484 	}
6485 
6486 	if (is_system_tablespace(table->space)) {
6487 		space_type = "System";
6488 	} else if (DICT_TF_HAS_SHARED_SPACE(table->flags)) {
6489 		space_type = "General";
6490 	} else {
6491 		space_type = "Single";
6492 	}
6493 
6494 	DBUG_ENTER("i_s_dict_fill_sys_tables");
6495 
6496 	fields = table_to_fill->field;
6497 
6498 	OK(fields[SYS_TABLES_ID]->store(longlong(table->id), TRUE));
6499 
6500 	OK(field_store_string(fields[SYS_TABLES_NAME], table->name.m_name));
6501 
6502 	OK(fields[SYS_TABLES_FLAG]->store(table->flags));
6503 
6504 	OK(fields[SYS_TABLES_NUM_COLUMN]->store(table->n_cols));
6505 
6506 	OK(fields[SYS_TABLES_SPACE]->store(table->space));
6507 
6508 	OK(field_store_string(fields[SYS_TABLES_FILE_FORMAT], file_format));
6509 
6510 	OK(field_store_string(fields[SYS_TABLES_ROW_FORMAT], row_format));
6511 
6512 	OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(page_size.is_compressed()
6513 						   ? page_size.physical()
6514 						   : 0, true));
6515 
6516 	OK(field_store_string(fields[SYS_TABLES_SPACE_TYPE], space_type));
6517 
6518 	OK(schema_table_store_record(thd, table_to_fill));
6519 
6520 	DBUG_RETURN(0);
6521 }
6522 /*******************************************************************//**
6523 Function to go through each record in SYS_TABLES table, and fill the
6524 information_schema.innodb_sys_tables table with related table information
6525 @return 0 on success */
6526 static
6527 int
i_s_sys_tables_fill_table(THD * thd,TABLE_LIST * tables,Item *)6528 i_s_sys_tables_fill_table(
6529 /*======================*/
6530 	THD*		thd,	/*!< in: thread */
6531 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
6532 	Item*		)	/*!< in: condition (not used) */
6533 {
6534 	btr_pcur_t	pcur;
6535 	const rec_t*	rec;
6536 	mem_heap_t*	heap;
6537 	mtr_t		mtr;
6538 
6539 	DBUG_ENTER("i_s_sys_tables_fill_table");
6540 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6541 
6542 	/* deny access to user without PROCESS_ACL privilege */
6543 	if (check_global_access(thd, PROCESS_ACL)) {
6544 		DBUG_RETURN(0);
6545 	}
6546 
6547 	heap = mem_heap_create(1000);
6548 	mutex_enter(&dict_sys->mutex);
6549 	mtr_start(&mtr);
6550 
6551 	rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6552 
6553 	while (rec) {
6554 		const char*	err_msg;
6555 		dict_table_t*	table_rec;
6556 
6557 		/* Create and populate a dict_table_t structure with
6558 		information from SYS_TABLES row */
6559 		err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6560 			heap, rec, &table_rec,
6561 			DICT_TABLE_LOAD_FROM_RECORD, &mtr);
6562 
6563 		mutex_exit(&dict_sys->mutex);
6564 
6565 		if (!err_msg) {
6566 			i_s_dict_fill_sys_tables(thd, table_rec, tables->table);
6567 		} else {
6568 			push_warning_printf(thd, Sql_condition::SL_WARNING,
6569 					    ER_CANT_FIND_SYSTEM_REC, "%s",
6570 					    err_msg);
6571 		}
6572 
6573 		/* Since dict_process_sys_tables_rec_and_mtr_commit()
6574 		is called with DICT_TABLE_LOAD_FROM_RECORD, the table_rec
6575 		is created in dict_process_sys_tables_rec(), we will
6576 		need to free it */
6577 		if (table_rec) {
6578 			dict_mem_table_free(table_rec);
6579 		}
6580 
6581 		mem_heap_empty(heap);
6582 
6583 		/* Get the next record */
6584 		mutex_enter(&dict_sys->mutex);
6585 		mtr_start(&mtr);
6586 		rec = dict_getnext_system(&pcur, &mtr);
6587 	}
6588 
6589 	mtr_commit(&mtr);
6590 	mutex_exit(&dict_sys->mutex);
6591 	mem_heap_free(heap);
6592 
6593 	DBUG_RETURN(0);
6594 }
6595 
6596 /*******************************************************************//**
6597 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tables
6598 @return 0 on success */
6599 static
6600 int
innodb_sys_tables_init(void * p)6601 innodb_sys_tables_init(
6602 /*===================*/
6603 	void*	p)	/*!< in/out: table schema object */
6604 {
6605 	ST_SCHEMA_TABLE*	schema;
6606 
6607 	DBUG_ENTER("innodb_sys_tables_init");
6608 
6609 	schema = (ST_SCHEMA_TABLE*) p;
6610 
6611 	schema->fields_info = innodb_sys_tables_fields_info;
6612 	schema->fill_table = i_s_sys_tables_fill_table;
6613 
6614 	DBUG_RETURN(0);
6615 }
6616 
6617 struct st_mysql_plugin	i_s_innodb_sys_tables =
6618 {
6619 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
6620 	/* int */
6621 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6622 
6623 	/* pointer to type-specific plugin descriptor */
6624 	/* void* */
6625 	STRUCT_FLD(info, &i_s_info),
6626 
6627 	/* plugin name */
6628 	/* const char* */
6629 	STRUCT_FLD(name, "INNODB_SYS_TABLES"),
6630 
6631 	/* plugin author (for SHOW PLUGINS) */
6632 	/* const char* */
6633 	STRUCT_FLD(author, plugin_author),
6634 
6635 	/* general descriptive text (for SHOW PLUGINS) */
6636 	/* const char* */
6637 	STRUCT_FLD(descr, "InnoDB SYS_TABLES"),
6638 
6639 	/* the plugin license (PLUGIN_LICENSE_XXX) */
6640 	/* int */
6641 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6642 
6643 	/* the function to invoke when plugin is loaded */
6644 	/* int (*)(void*); */
6645 	STRUCT_FLD(init, innodb_sys_tables_init),
6646 
6647 	/* the function to invoke when plugin is unloaded */
6648 	/* int (*)(void*); */
6649 	STRUCT_FLD(deinit, i_s_common_deinit),
6650 
6651 	/* plugin version (for SHOW PLUGINS) */
6652 	/* unsigned int */
6653 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
6654 
6655 	/* struct st_mysql_show_var* */
6656 	STRUCT_FLD(status_vars, NULL),
6657 
6658 	/* struct st_mysql_sys_var** */
6659 	STRUCT_FLD(system_vars, NULL),
6660 
6661 	/* reserved for dependency checking */
6662 	/* void* */
6663 	STRUCT_FLD(__reserved1, NULL),
6664 
6665 	/* Plugin flags */
6666 	/* unsigned long */
6667 	STRUCT_FLD(flags, 0UL),
6668 };
6669 
6670 /**  SYS_TABLESTATS  ***********************************************/
6671 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_TABLESTATS */
6672 static ST_FIELD_INFO	innodb_sys_tablestats_fields_info[] =
6673 {
6674 #define SYS_TABLESTATS_ID		0
6675 	{STRUCT_FLD(field_name,		"TABLE_ID"),
6676 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6677 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6678 	 STRUCT_FLD(value,		0),
6679 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6680 	 STRUCT_FLD(old_name,		""),
6681 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6682 
6683 #define SYS_TABLESTATS_NAME		1
6684 	{STRUCT_FLD(field_name,		"NAME"),
6685 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
6686 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6687 	 STRUCT_FLD(value,		0),
6688 	 STRUCT_FLD(field_flags,	0),
6689 	 STRUCT_FLD(old_name,		""),
6690 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6691 
6692 #define SYS_TABLESTATS_INIT		2
6693 	{STRUCT_FLD(field_name,		"STATS_INITIALIZED"),
6694 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
6695 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
6696 	 STRUCT_FLD(value,		0),
6697 	 STRUCT_FLD(field_flags,	0),
6698 	 STRUCT_FLD(old_name,		""),
6699 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6700 
6701 #define SYS_TABLESTATS_NROW		3
6702 	{STRUCT_FLD(field_name,		"NUM_ROWS"),
6703 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6704 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6705 	 STRUCT_FLD(value,		0),
6706 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6707 	 STRUCT_FLD(old_name,		""),
6708 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6709 
6710 #define SYS_TABLESTATS_CLUST_SIZE	4
6711 	{STRUCT_FLD(field_name,		"CLUST_INDEX_SIZE"),
6712 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6713 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6714 	 STRUCT_FLD(value,		0),
6715 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6716 	 STRUCT_FLD(old_name,		""),
6717 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6718 
6719 #define SYS_TABLESTATS_INDEX_SIZE	5
6720 	{STRUCT_FLD(field_name,		"OTHER_INDEX_SIZE"),
6721 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6722 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6723 	 STRUCT_FLD(value,		0),
6724 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6725 	 STRUCT_FLD(old_name,		""),
6726 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6727 
6728 #define SYS_TABLESTATS_MODIFIED		6
6729 	{STRUCT_FLD(field_name,		"MODIFIED_COUNTER"),
6730 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6731 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6732 	 STRUCT_FLD(value,		0),
6733 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6734 	 STRUCT_FLD(old_name,		""),
6735 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6736 
6737 #define SYS_TABLESTATS_AUTONINC		7
6738 	{STRUCT_FLD(field_name,		"AUTOINC"),
6739 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6740 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6741 	 STRUCT_FLD(value,		0),
6742 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6743 	 STRUCT_FLD(old_name,		""),
6744 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6745 
6746 #define SYS_TABLESTATS_TABLE_REF_COUNT	8
6747 	{STRUCT_FLD(field_name,		"REF_COUNT"),
6748 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
6749 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
6750 	 STRUCT_FLD(value,		0),
6751 	 STRUCT_FLD(field_flags,	0),
6752 	 STRUCT_FLD(old_name,		""),
6753 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
6754 
6755 	END_OF_ST_FIELD_INFO
6756 };
6757 
6758 /** Populate information_schema.innodb_sys_tablestats table with information
6759 from SYS_TABLES.
6760 @param[in]	thd		thread ID
6761 @param[in,out]	table		table
6762 @param[in]	ref_count	table reference count
6763 @param[in,out]	table_to_fill	fill this table
6764 @return 0 on success */
6765 static
6766 int
i_s_dict_fill_sys_tablestats(THD * thd,dict_table_t * table,ulint ref_count,TABLE * table_to_fill)6767 i_s_dict_fill_sys_tablestats(
6768 	THD*		thd,
6769 	dict_table_t*	table,
6770 	ulint		ref_count,
6771 	TABLE*		table_to_fill)
6772 {
6773 	Field**		fields;
6774 
6775 	DBUG_ENTER("i_s_dict_fill_sys_tablestats");
6776 
6777 	fields = table_to_fill->field;
6778 
6779 	OK(fields[SYS_TABLESTATS_ID]->store(longlong(table->id), TRUE));
6780 
6781 	OK(field_store_string(fields[SYS_TABLESTATS_NAME],
6782 			      table->name.m_name));
6783 
6784 	dict_table_stats_lock(table, RW_S_LATCH);
6785 
6786 	if (table->stat_initialized) {
6787 		OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6788 				      "Initialized"));
6789 
6790 		OK(fields[SYS_TABLESTATS_NROW]->store(table->stat_n_rows,
6791 						      true));
6792 
6793 		OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(
6794 			   table->stat_clustered_index_size, true));
6795 
6796 		OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(
6797 			   table->stat_sum_of_other_index_sizes, true));
6798 
6799 		OK(fields[SYS_TABLESTATS_MODIFIED]->store(
6800 			   table->stat_modified_counter, true));
6801 	} else {
6802 		OK(field_store_string(fields[SYS_TABLESTATS_INIT],
6803 				      "Uninitialized"));
6804 
6805 		OK(fields[SYS_TABLESTATS_NROW]->store(0, true));
6806 
6807 		OK(fields[SYS_TABLESTATS_CLUST_SIZE]->store(0, true));
6808 
6809 		OK(fields[SYS_TABLESTATS_INDEX_SIZE]->store(0, true));
6810 
6811 		OK(fields[SYS_TABLESTATS_MODIFIED]->store(0, true));
6812 	}
6813 
6814 	dict_table_stats_unlock(table, RW_S_LATCH);
6815 
6816 	OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, true));
6817 
6818 	OK(fields[SYS_TABLESTATS_TABLE_REF_COUNT]->store(ref_count, true));
6819 
6820 	OK(schema_table_store_record(thd, table_to_fill));
6821 
6822 	DBUG_RETURN(0);
6823 }
6824 
6825 /*******************************************************************//**
6826 Function to go through each record in SYS_TABLES table, and fill the
6827 information_schema.innodb_sys_tablestats table with table statistics
6828 related information
6829 @return 0 on success */
6830 static
6831 int
i_s_sys_tables_fill_table_stats(THD * thd,TABLE_LIST * tables,Item *)6832 i_s_sys_tables_fill_table_stats(
6833 /*============================*/
6834 	THD*		thd,	/*!< in: thread */
6835 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
6836 	Item*		)	/*!< in: condition (not used) */
6837 {
6838 	btr_pcur_t	pcur;
6839 	const rec_t*	rec;
6840 	mem_heap_t*	heap;
6841 	mtr_t		mtr;
6842 
6843 	DBUG_ENTER("i_s_sys_tables_fill_table_stats");
6844 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
6845 
6846 	/* deny access to user without PROCESS_ACL privilege */
6847 	if (check_global_access(thd, PROCESS_ACL)) {
6848 		DBUG_RETURN(0);
6849 	}
6850 
6851 	heap = mem_heap_create(1000);
6852 	mutex_enter(&dict_sys->mutex);
6853 	mtr_start(&mtr);
6854 
6855 	rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
6856 
6857 	while (rec) {
6858 		const char*	err_msg;
6859 		dict_table_t*	table_rec;
6860 		ulint		ref_count = 0;
6861 
6862 		/* Fetch the dict_table_t structure corresponding to
6863 		this SYS_TABLES record */
6864 		err_msg = dict_process_sys_tables_rec_and_mtr_commit(
6865 			heap, rec, &table_rec,
6866 			DICT_TABLE_LOAD_FROM_CACHE, &mtr);
6867 
6868 		if (table_rec != NULL) {
6869 			ut_ad(err_msg == NULL);
6870 
6871 			ref_count = table_rec->get_ref_count();
6872 
6873 			/* Protect the dict_table_t object by incrementing
6874 			the reference count. */
6875 			table_rec->acquire();
6876 		}
6877 
6878 		mutex_exit(&dict_sys->mutex);
6879 
6880 		DBUG_EXECUTE_IF("test_sys_tablestats", {
6881 			if (strcmp("test/t1", table_rec->name.m_name) == 0 ) {
6882 				DEBUG_SYNC_C("dict_table_not_protected");
6883 			}});
6884 
6885 		if (table_rec != NULL) {
6886 			i_s_dict_fill_sys_tablestats(thd, table_rec, ref_count,
6887 						     tables->table);
6888 		} else {
6889 			push_warning_printf(thd, Sql_condition::SL_WARNING,
6890 					    ER_CANT_FIND_SYSTEM_REC, "%s",
6891 					    err_msg);
6892 		}
6893 
6894 		mem_heap_empty(heap);
6895 
6896 		/* Get the next record */
6897 		mutex_enter(&dict_sys->mutex);
6898 
6899 		if (table_rec != NULL) {
6900 			table_rec->release();
6901 		}
6902 
6903 		mtr_start(&mtr);
6904 		rec = dict_getnext_system(&pcur, &mtr);
6905 	}
6906 
6907 	mtr_commit(&mtr);
6908 	mutex_exit(&dict_sys->mutex);
6909 	mem_heap_free(heap);
6910 
6911 	DBUG_RETURN(0);
6912 }
6913 
6914 /*******************************************************************//**
6915 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_tablestats
6916 @return 0 on success */
6917 static
6918 int
innodb_sys_tablestats_init(void * p)6919 innodb_sys_tablestats_init(
6920 /*=======================*/
6921 	void*	p)	/*!< in/out: table schema object */
6922 {
6923 	ST_SCHEMA_TABLE*	schema;
6924 
6925 	DBUG_ENTER("innodb_sys_tablestats_init");
6926 
6927 	schema = (ST_SCHEMA_TABLE*) p;
6928 
6929 	schema->fields_info = innodb_sys_tablestats_fields_info;
6930 	schema->fill_table = i_s_sys_tables_fill_table_stats;
6931 
6932 	DBUG_RETURN(0);
6933 }
6934 
6935 struct st_mysql_plugin	i_s_innodb_sys_tablestats =
6936 {
6937 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
6938 	/* int */
6939 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
6940 
6941 	/* pointer to type-specific plugin descriptor */
6942 	/* void* */
6943 	STRUCT_FLD(info, &i_s_info),
6944 
6945 	/* plugin name */
6946 	/* const char* */
6947 	STRUCT_FLD(name, "INNODB_SYS_TABLESTATS"),
6948 
6949 	/* plugin author (for SHOW PLUGINS) */
6950 	/* const char* */
6951 	STRUCT_FLD(author, plugin_author),
6952 
6953 	/* general descriptive text (for SHOW PLUGINS) */
6954 	/* const char* */
6955 	STRUCT_FLD(descr, "InnoDB SYS_TABLESTATS"),
6956 
6957 	/* the plugin license (PLUGIN_LICENSE_XXX) */
6958 	/* int */
6959 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
6960 
6961 	/* the function to invoke when plugin is loaded */
6962 	/* int (*)(void*); */
6963 	STRUCT_FLD(init, innodb_sys_tablestats_init),
6964 
6965 	/* the function to invoke when plugin is unloaded */
6966 	/* int (*)(void*); */
6967 	STRUCT_FLD(deinit, i_s_common_deinit),
6968 
6969 	/* plugin version (for SHOW PLUGINS) */
6970 	/* unsigned int */
6971 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
6972 
6973 	/* struct st_mysql_show_var* */
6974 	STRUCT_FLD(status_vars, NULL),
6975 
6976 	/* struct st_mysql_sys_var** */
6977 	STRUCT_FLD(system_vars, NULL),
6978 
6979 	/* reserved for dependency checking */
6980 	/* void* */
6981 	STRUCT_FLD(__reserved1, NULL),
6982 
6983 	/* Plugin flags */
6984 	/* unsigned long */
6985 	STRUCT_FLD(flags, 0UL),
6986 };
6987 
6988 /**  SYS_INDEXES  **************************************************/
6989 /* Fields of the dynamic table INFORMATION_SCHEMA.SYS_INDEXES */
6990 static ST_FIELD_INFO	innodb_sysindex_fields_info[] =
6991 {
6992 #define SYS_INDEX_ID		0
6993 	{STRUCT_FLD(field_name,		"INDEX_ID"),
6994 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
6995 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
6996 	 STRUCT_FLD(value,		0),
6997 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
6998 	 STRUCT_FLD(old_name,		""),
6999 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7000 
7001 #define SYS_INDEX_NAME		1
7002 	{STRUCT_FLD(field_name,		"NAME"),
7003 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7004 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7005 	 STRUCT_FLD(value,		0),
7006 	 STRUCT_FLD(field_flags,	0),
7007 	 STRUCT_FLD(old_name,		""),
7008 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7009 
7010 #define SYS_INDEX_TABLE_ID	2
7011 	{STRUCT_FLD(field_name,		"TABLE_ID"),
7012 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
7013 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
7014 	 STRUCT_FLD(value,		0),
7015 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7016 	 STRUCT_FLD(old_name,		""),
7017 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7018 
7019 #define SYS_INDEX_TYPE		3
7020 	{STRUCT_FLD(field_name,		"TYPE"),
7021 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7022 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7023 	 STRUCT_FLD(value,		0),
7024 	 STRUCT_FLD(field_flags,	0),
7025 	 STRUCT_FLD(old_name,		""),
7026 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7027 
7028 #define SYS_INDEX_NUM_FIELDS	4
7029 	{STRUCT_FLD(field_name,		"N_FIELDS"),
7030 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7031 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7032 	 STRUCT_FLD(value,		0),
7033 	 STRUCT_FLD(field_flags,	0),
7034 	 STRUCT_FLD(old_name,		""),
7035 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7036 
7037 #define SYS_INDEX_PAGE_NO	5
7038 	{STRUCT_FLD(field_name,		"PAGE_NO"),
7039 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7040 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7041 	 STRUCT_FLD(value,		0),
7042 	 STRUCT_FLD(field_flags,	0),
7043 	 STRUCT_FLD(old_name,		""),
7044 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7045 
7046 #define SYS_INDEX_SPACE		6
7047 	{STRUCT_FLD(field_name,		"SPACE"),
7048 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7049 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7050 	 STRUCT_FLD(value,		0),
7051 	 STRUCT_FLD(field_flags,	0),
7052 	 STRUCT_FLD(old_name,		""),
7053 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7054 
7055 #define SYS_INDEX_MERGE_THRESHOLD 7
7056 	{STRUCT_FLD(field_name,		"MERGE_THRESHOLD"),
7057 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7058 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7059 	 STRUCT_FLD(value,		0),
7060 	 STRUCT_FLD(field_flags,	0),
7061 	 STRUCT_FLD(old_name,		""),
7062 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7063 
7064 	END_OF_ST_FIELD_INFO
7065 };
7066 
7067 /**********************************************************************//**
7068 Function to populate the information_schema.innodb_sys_indexes table with
7069 collected index information
7070 @return 0 on success */
7071 static
7072 int
i_s_dict_fill_sys_indexes(THD * thd,table_id_t table_id,dict_index_t * index,TABLE * table_to_fill)7073 i_s_dict_fill_sys_indexes(
7074 /*======================*/
7075 	THD*		thd,		/*!< in: thread */
7076 	table_id_t	table_id,	/*!< in: table id */
7077 	dict_index_t*	index,		/*!< in: populated dict_index_t
7078 					struct with index info */
7079 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7080 {
7081 	Field**		fields;
7082 
7083 	DBUG_ENTER("i_s_dict_fill_sys_indexes");
7084 
7085 	fields = table_to_fill->field;
7086 
7087 	OK(field_store_index_name(fields[SYS_INDEX_NAME], index->name));
7088 
7089 	OK(fields[SYS_INDEX_ID]->store(longlong(index->id), true));
7090 
7091 	OK(fields[SYS_INDEX_TABLE_ID]->store(longlong(table_id), true));
7092 
7093 	OK(fields[SYS_INDEX_TYPE]->store(index->type));
7094 
7095 	OK(fields[SYS_INDEX_NUM_FIELDS]->store(index->n_fields));
7096 
7097 	/* FIL_NULL is ULINT32_UNDEFINED */
7098 	if (index->page == FIL_NULL) {
7099 		OK(fields[SYS_INDEX_PAGE_NO]->store(-1));
7100 	} else {
7101 		OK(fields[SYS_INDEX_PAGE_NO]->store(index->page));
7102 	}
7103 
7104 	OK(fields[SYS_INDEX_SPACE]->store(index->space));
7105 
7106 	OK(fields[SYS_INDEX_MERGE_THRESHOLD]->store(index->merge_threshold));
7107 
7108 	OK(schema_table_store_record(thd, table_to_fill));
7109 
7110 	DBUG_RETURN(0);
7111 }
7112 /*******************************************************************//**
7113 Function to go through each record in SYS_INDEXES table, and fill the
7114 information_schema.innodb_sys_indexes table with related index information
7115 @return 0 on success */
7116 static
7117 int
i_s_sys_indexes_fill_table(THD * thd,TABLE_LIST * tables,Item *)7118 i_s_sys_indexes_fill_table(
7119 /*=======================*/
7120 	THD*		thd,	/*!< in: thread */
7121 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7122 	Item*		)	/*!< in: condition (not used) */
7123 {
7124 	btr_pcur_t		pcur;
7125 	const rec_t*		rec;
7126 	mem_heap_t*		heap;
7127 	mtr_t			mtr;
7128 
7129 	DBUG_ENTER("i_s_sys_indexes_fill_table");
7130 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7131 
7132 	/* deny access to user without PROCESS_ACL privilege */
7133 	if (check_global_access(thd, PROCESS_ACL)) {
7134 		DBUG_RETURN(0);
7135 	}
7136 
7137 	heap = mem_heap_create(1000);
7138 	mutex_enter(&dict_sys->mutex);
7139 	mtr_start(&mtr);
7140 
7141 	/* Start scan the SYS_INDEXES table */
7142 	rec = dict_startscan_system(&pcur, &mtr, SYS_INDEXES);
7143 
7144 	/* Process each record in the table */
7145 	while (rec) {
7146 		const char*	err_msg;
7147 		table_id_t	table_id;
7148 		dict_index_t	index_rec;
7149 
7150 		/* Populate a dict_index_t structure with information from
7151 		a SYS_INDEXES row */
7152 		err_msg = dict_process_sys_indexes_rec(heap, rec, &index_rec,
7153 						       &table_id);
7154 
7155 		mtr_commit(&mtr);
7156 		mutex_exit(&dict_sys->mutex);
7157 
7158 		if (!err_msg) {
7159 			i_s_dict_fill_sys_indexes(thd, table_id, &index_rec,
7160 						 tables->table);
7161 		} else {
7162 			push_warning_printf(thd, Sql_condition::SL_WARNING,
7163 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7164 					    err_msg);
7165 		}
7166 
7167 		mem_heap_empty(heap);
7168 
7169 		/* Get the next record */
7170 		mutex_enter(&dict_sys->mutex);
7171 		mtr_start(&mtr);
7172 		rec = dict_getnext_system(&pcur, &mtr);
7173 	}
7174 
7175 	mtr_commit(&mtr);
7176 	mutex_exit(&dict_sys->mutex);
7177 	mem_heap_free(heap);
7178 
7179 	DBUG_RETURN(0);
7180 }
7181 /*******************************************************************//**
7182 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_indexes
7183 @return 0 on success */
7184 static
7185 int
innodb_sys_indexes_init(void * p)7186 innodb_sys_indexes_init(
7187 /*====================*/
7188 	void*	p)	/*!< in/out: table schema object */
7189 {
7190 	ST_SCHEMA_TABLE*	schema;
7191 
7192 	DBUG_ENTER("innodb_sys_indexes_init");
7193 
7194 	schema = (ST_SCHEMA_TABLE*) p;
7195 
7196 	schema->fields_info = innodb_sysindex_fields_info;
7197 	schema->fill_table = i_s_sys_indexes_fill_table;
7198 
7199 	DBUG_RETURN(0);
7200 }
7201 
7202 struct st_mysql_plugin	i_s_innodb_sys_indexes =
7203 {
7204 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7205 	/* int */
7206 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7207 
7208 	/* pointer to type-specific plugin descriptor */
7209 	/* void* */
7210 	STRUCT_FLD(info, &i_s_info),
7211 
7212 	/* plugin name */
7213 	/* const char* */
7214 	STRUCT_FLD(name, "INNODB_SYS_INDEXES"),
7215 
7216 	/* plugin author (for SHOW PLUGINS) */
7217 	/* const char* */
7218 	STRUCT_FLD(author, plugin_author),
7219 
7220 	/* general descriptive text (for SHOW PLUGINS) */
7221 	/* const char* */
7222 	STRUCT_FLD(descr, "InnoDB SYS_INDEXES"),
7223 
7224 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7225 	/* int */
7226 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7227 
7228 	/* the function to invoke when plugin is loaded */
7229 	/* int (*)(void*); */
7230 	STRUCT_FLD(init, innodb_sys_indexes_init),
7231 
7232 	/* the function to invoke when plugin is unloaded */
7233 	/* int (*)(void*); */
7234 	STRUCT_FLD(deinit, i_s_common_deinit),
7235 
7236 	/* plugin version (for SHOW PLUGINS) */
7237 	/* unsigned int */
7238 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7239 
7240 	/* struct st_mysql_show_var* */
7241 	STRUCT_FLD(status_vars, NULL),
7242 
7243 	/* struct st_mysql_sys_var** */
7244 	STRUCT_FLD(system_vars, NULL),
7245 
7246 	/* reserved for dependency checking */
7247 	/* void* */
7248 	STRUCT_FLD(__reserved1, NULL),
7249 
7250 	/* Plugin flags */
7251 	/* unsigned long */
7252 	STRUCT_FLD(flags, 0UL),
7253 };
7254 
7255 /**  SYS_COLUMNS  **************************************************/
7256 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_COLUMNS */
7257 static ST_FIELD_INFO	innodb_sys_columns_fields_info[] =
7258 {
7259 #define SYS_COLUMN_TABLE_ID		0
7260 	{STRUCT_FLD(field_name,		"TABLE_ID"),
7261 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
7262 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
7263 	 STRUCT_FLD(value,		0),
7264 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7265 	 STRUCT_FLD(old_name,		""),
7266 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7267 
7268 #define SYS_COLUMN_NAME		1
7269 	{STRUCT_FLD(field_name,		"NAME"),
7270 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7271 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7272 	 STRUCT_FLD(value,		0),
7273 	 STRUCT_FLD(field_flags,	0),
7274 	 STRUCT_FLD(old_name,		""),
7275 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7276 
7277 #define SYS_COLUMN_POSITION	2
7278 	{STRUCT_FLD(field_name,		"POS"),
7279 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
7280 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
7281 	 STRUCT_FLD(value,		0),
7282 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7283 	 STRUCT_FLD(old_name,		""),
7284 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7285 
7286 #define SYS_COLUMN_MTYPE		3
7287 	{STRUCT_FLD(field_name,		"MTYPE"),
7288 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7289 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7290 	 STRUCT_FLD(value,		0),
7291 	 STRUCT_FLD(field_flags,	0),
7292 	 STRUCT_FLD(old_name,		""),
7293 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7294 
7295 #define SYS_COLUMN__PRTYPE	4
7296 	{STRUCT_FLD(field_name,		"PRTYPE"),
7297 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7298 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7299 	 STRUCT_FLD(value,		0),
7300 	 STRUCT_FLD(field_flags,	0),
7301 	 STRUCT_FLD(old_name,		""),
7302 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7303 
7304 #define SYS_COLUMN_COLUMN_LEN	5
7305 	{STRUCT_FLD(field_name,		"LEN"),
7306 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7307 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7308 	 STRUCT_FLD(value,		0),
7309 	 STRUCT_FLD(field_flags,	0),
7310 	 STRUCT_FLD(old_name,		""),
7311 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7312 
7313 	END_OF_ST_FIELD_INFO
7314 };
7315 
7316 /**********************************************************************//**
7317 Function to populate the information_schema.innodb_sys_columns with
7318 related column information
7319 @return 0 on success */
7320 static
7321 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)7322 i_s_dict_fill_sys_columns(
7323 /*======================*/
7324 	THD*		thd,		/*!< in: thread */
7325 	table_id_t	table_id,	/*!< in: table ID */
7326 	const char*	col_name,	/*!< in: column name */
7327 	dict_col_t*	column,		/*!< in: dict_col_t struct holding
7328 					more column information */
7329 	ulint		nth_v_col,	/*!< in: virtual column, its
7330 					sequence number (nth virtual col) */
7331 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7332 {
7333 	Field**		fields;
7334 
7335 	DBUG_ENTER("i_s_dict_fill_sys_columns");
7336 
7337 	fields = table_to_fill->field;
7338 
7339 	OK(fields[SYS_COLUMN_TABLE_ID]->store((longlong)table_id, true));
7340 
7341 	OK(field_store_string(fields[SYS_COLUMN_NAME], col_name));
7342 
7343 	if (dict_col_is_virtual(column)) {
7344 		ulint	pos = dict_create_v_col_pos(nth_v_col, column->ind);
7345 		OK(fields[SYS_COLUMN_POSITION]->store(pos, true));
7346 	} else {
7347 		OK(fields[SYS_COLUMN_POSITION]->store(column->ind, true));
7348 	}
7349 
7350 	OK(fields[SYS_COLUMN_MTYPE]->store(column->mtype));
7351 
7352 	OK(fields[SYS_COLUMN__PRTYPE]->store(column->prtype));
7353 
7354 	OK(fields[SYS_COLUMN_COLUMN_LEN]->store(column->len));
7355 
7356 	OK(schema_table_store_record(thd, table_to_fill));
7357 
7358 	DBUG_RETURN(0);
7359 }
7360 /*******************************************************************//**
7361 Function to fill information_schema.innodb_sys_columns with information
7362 collected by scanning SYS_COLUMNS table.
7363 @return 0 on success */
7364 static
7365 int
i_s_sys_columns_fill_table(THD * thd,TABLE_LIST * tables,Item *)7366 i_s_sys_columns_fill_table(
7367 /*=======================*/
7368 	THD*		thd,	/*!< in: thread */
7369 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7370 	Item*		)	/*!< in: condition (not used) */
7371 {
7372 	btr_pcur_t	pcur;
7373 	const rec_t*	rec;
7374 	const char*	col_name;
7375 	mem_heap_t*	heap;
7376 	mtr_t		mtr;
7377 
7378 	DBUG_ENTER("i_s_sys_columns_fill_table");
7379 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7380 
7381 	/* deny access to user without PROCESS_ACL privilege */
7382 	if (check_global_access(thd, PROCESS_ACL)) {
7383 		DBUG_RETURN(0);
7384 	}
7385 
7386 	heap = mem_heap_create(1000);
7387 	mutex_enter(&dict_sys->mutex);
7388 	mtr_start(&mtr);
7389 
7390 	rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
7391 
7392 	while (rec) {
7393 		const char*	err_msg;
7394 		dict_col_t	column_rec;
7395 		table_id_t	table_id;
7396 		ulint		nth_v_col;
7397 
7398 		/* populate a dict_col_t structure with information from
7399 		a SYS_COLUMNS row */
7400 		err_msg = dict_process_sys_columns_rec(heap, rec, &column_rec,
7401 						       &table_id, &col_name,
7402 						       &nth_v_col);
7403 
7404 		mtr_commit(&mtr);
7405 		mutex_exit(&dict_sys->mutex);
7406 
7407 		if (!err_msg) {
7408 			i_s_dict_fill_sys_columns(thd, table_id, col_name,
7409 						 &column_rec, nth_v_col,
7410 						 tables->table);
7411 		} else {
7412 			push_warning_printf(thd, Sql_condition::SL_WARNING,
7413 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7414 					    err_msg);
7415 		}
7416 
7417 		mem_heap_empty(heap);
7418 
7419 		/* Get the next record */
7420 		mutex_enter(&dict_sys->mutex);
7421 		mtr_start(&mtr);
7422 		rec = dict_getnext_system(&pcur, &mtr);
7423 	}
7424 
7425 	mtr_commit(&mtr);
7426 	mutex_exit(&dict_sys->mutex);
7427 	mem_heap_free(heap);
7428 
7429 	DBUG_RETURN(0);
7430 }
7431 /*******************************************************************//**
7432 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_columns
7433 @return 0 on success */
7434 static
7435 int
innodb_sys_columns_init(void * p)7436 innodb_sys_columns_init(
7437 /*====================*/
7438 	void*	p)	/*!< in/out: table schema object */
7439 {
7440 	ST_SCHEMA_TABLE*	schema;
7441 
7442 	DBUG_ENTER("innodb_sys_columns_init");
7443 
7444 	schema = (ST_SCHEMA_TABLE*) p;
7445 
7446 	schema->fields_info = innodb_sys_columns_fields_info;
7447 	schema->fill_table = i_s_sys_columns_fill_table;
7448 
7449 	DBUG_RETURN(0);
7450 }
7451 
7452 struct st_mysql_plugin	i_s_innodb_sys_columns =
7453 {
7454 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7455 	/* int */
7456 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7457 
7458 	/* pointer to type-specific plugin descriptor */
7459 	/* void* */
7460 	STRUCT_FLD(info, &i_s_info),
7461 
7462 	/* plugin name */
7463 	/* const char* */
7464 	STRUCT_FLD(name, "INNODB_SYS_COLUMNS"),
7465 
7466 	/* plugin author (for SHOW PLUGINS) */
7467 	/* const char* */
7468 	STRUCT_FLD(author, plugin_author),
7469 
7470 	/* general descriptive text (for SHOW PLUGINS) */
7471 	/* const char* */
7472 	STRUCT_FLD(descr, "InnoDB SYS_COLUMNS"),
7473 
7474 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7475 	/* int */
7476 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7477 
7478 	/* the function to invoke when plugin is loaded */
7479 	/* int (*)(void*); */
7480 	STRUCT_FLD(init, innodb_sys_columns_init),
7481 
7482 	/* the function to invoke when plugin is unloaded */
7483 	/* int (*)(void*); */
7484 	STRUCT_FLD(deinit, i_s_common_deinit),
7485 
7486 	/* plugin version (for SHOW PLUGINS) */
7487 	/* unsigned int */
7488 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7489 
7490 	/* struct st_mysql_show_var* */
7491 	STRUCT_FLD(status_vars, NULL),
7492 
7493 	/* struct st_mysql_sys_var** */
7494 	STRUCT_FLD(system_vars, NULL),
7495 
7496 	/* reserved for dependency checking */
7497 	/* void* */
7498 	STRUCT_FLD(__reserved1, NULL),
7499 
7500 	/* Plugin flags */
7501 	/* unsigned long */
7502 	STRUCT_FLD(flags, 0UL),
7503 };
7504 
7505 /**  SYS_VIRTUAL **************************************************/
7506 /** Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL */
7507 static ST_FIELD_INFO	innodb_sys_virtual_fields_info[] =
7508 {
7509 #define SYS_VIRTUAL_TABLE_ID		0
7510 	{STRUCT_FLD(field_name,		"TABLE_ID"),
7511 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
7512 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
7513 	 STRUCT_FLD(value,		0),
7514 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7515 	 STRUCT_FLD(old_name,		""),
7516 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7517 
7518 #define SYS_VIRTUAL_POS			1
7519 	{STRUCT_FLD(field_name,		"POS"),
7520 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7521 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7522 	 STRUCT_FLD(value,		0),
7523 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7524 	 STRUCT_FLD(old_name,		""),
7525 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7526 
7527 #define SYS_VIRTUAL_BASE_POS		2
7528 	{STRUCT_FLD(field_name,		"BASE_POS"),
7529 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7530 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7531 	 STRUCT_FLD(value,		0),
7532 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7533 	 STRUCT_FLD(old_name,		""),
7534 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7535 
7536 	END_OF_ST_FIELD_INFO
7537 };
7538 
7539 /** Function to populate the information_schema.innodb_sys_virtual with
7540 related information
7541 param[in]	thd		thread
7542 param[in]	table_id	table ID
7543 param[in]	pos		virtual column position
7544 param[in]	base_pos	base column position
7545 param[in,out]	table_to_fill	fill this table
7546 @return 0 on success */
7547 static
7548 int
i_s_dict_fill_sys_virtual(THD * thd,table_id_t table_id,ulint pos,ulint base_pos,TABLE * table_to_fill)7549 i_s_dict_fill_sys_virtual(
7550 	THD*		thd,
7551 	table_id_t	table_id,
7552 	ulint		pos,
7553 	ulint		base_pos,
7554 	TABLE*		table_to_fill)
7555 {
7556 	Field**		fields;
7557 
7558 	DBUG_ENTER("i_s_dict_fill_sys_virtual");
7559 
7560 	fields = table_to_fill->field;
7561 
7562 	OK(fields[SYS_VIRTUAL_TABLE_ID]->store(table_id, true));
7563 
7564 	OK(fields[SYS_VIRTUAL_POS]->store(pos, true));
7565 
7566 	OK(fields[SYS_VIRTUAL_BASE_POS]->store(base_pos, true));
7567 
7568 	OK(schema_table_store_record(thd, table_to_fill));
7569 
7570 	DBUG_RETURN(0);
7571 }
7572 
7573 /** Function to fill information_schema.innodb_sys_virtual with information
7574 collected by scanning SYS_VIRTUAL table.
7575 param[in]	thd		thread
7576 param[in,out]	tables		tables to fill
7577 param[in]	item		condition (not used)
7578 @return 0 on success */
7579 static
7580 int
i_s_sys_virtual_fill_table(THD * thd,TABLE_LIST * tables,Item *)7581 i_s_sys_virtual_fill_table(
7582 	THD*		thd,
7583 	TABLE_LIST*	tables,
7584 	Item*		)
7585 {
7586 	btr_pcur_t	pcur;
7587 	const rec_t*	rec;
7588 	ulint		pos;
7589 	ulint		base_pos;
7590 	mem_heap_t*	heap;
7591 	mtr_t		mtr;
7592 
7593 	DBUG_ENTER("i_s_sys_virtual_fill_table");
7594 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7595 
7596 	/* deny access to user without PROCESS_ACL privilege */
7597 	if (check_global_access(thd, PROCESS_ACL)) {
7598 		DBUG_RETURN(0);
7599 	}
7600 
7601 	heap = mem_heap_create(1000);
7602 	mutex_enter(&dict_sys->mutex);
7603 	mtr_start(&mtr);
7604 
7605 	rec = dict_startscan_system(&pcur, &mtr, SYS_VIRTUAL);
7606 
7607 	while (rec) {
7608 		const char*	err_msg;
7609 		table_id_t	table_id;
7610 
7611 		/* populate a dict_col_t structure with information from
7612 		a SYS_VIRTUAL row */
7613 		err_msg = dict_process_sys_virtual_rec(heap, rec,
7614 						       &table_id, &pos,
7615 						       &base_pos);
7616 
7617 		mtr_commit(&mtr);
7618 		mutex_exit(&dict_sys->mutex);
7619 
7620 		if (!err_msg) {
7621 			i_s_dict_fill_sys_virtual(thd, table_id, pos, base_pos,
7622 						  tables->table);
7623 		} else {
7624 			push_warning_printf(thd, Sql_condition::SL_WARNING,
7625 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7626 					    err_msg);
7627 		}
7628 
7629 		mem_heap_empty(heap);
7630 
7631 		/* Get the next record */
7632 		mutex_enter(&dict_sys->mutex);
7633 		mtr_start(&mtr);
7634 		rec = dict_getnext_system(&pcur, &mtr);
7635 	}
7636 
7637 	mtr_commit(&mtr);
7638 	mutex_exit(&dict_sys->mutex);
7639 	mem_heap_free(heap);
7640 
7641 	DBUG_RETURN(0);
7642 }
7643 
7644 /** Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_virtual
7645 param[in,out]	p	table schema object
7646 @return 0 on success */
7647 static
7648 int
innodb_sys_virtual_init(void * p)7649 innodb_sys_virtual_init(
7650 	void*	p)
7651 {
7652 	ST_SCHEMA_TABLE*	schema;
7653 
7654 	DBUG_ENTER("innodb_sys_virtual_init");
7655 
7656 	schema = (ST_SCHEMA_TABLE*) p;
7657 
7658 	schema->fields_info = innodb_sys_virtual_fields_info;
7659 	schema->fill_table = i_s_sys_virtual_fill_table;
7660 
7661 	DBUG_RETURN(0);
7662 }
7663 
7664 struct st_mysql_plugin	i_s_innodb_sys_virtual =
7665 {
7666 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7667 	/* int */
7668 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7669 
7670 	/* pointer to type-specific plugin descriptor */
7671 	/* void* */
7672 	STRUCT_FLD(info, &i_s_info),
7673 
7674 	/* plugin name */
7675 	/* const char* */
7676 	STRUCT_FLD(name, "INNODB_SYS_VIRTUAL"),
7677 
7678 	/* plugin author (for SHOW PLUGINS) */
7679 	/* const char* */
7680 	STRUCT_FLD(author, plugin_author),
7681 
7682 	/* general descriptive text (for SHOW PLUGINS) */
7683 	/* const char* */
7684 	STRUCT_FLD(descr, "InnoDB SYS_VIRTUAL"),
7685 
7686 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7687 	/* int */
7688 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7689 
7690 	/* the function to invoke when plugin is loaded */
7691 	/* int (*)(void*); */
7692 	STRUCT_FLD(init, innodb_sys_virtual_init),
7693 
7694 	/* the function to invoke when plugin is unloaded */
7695 	/* int (*)(void*); */
7696 	STRUCT_FLD(deinit, i_s_common_deinit),
7697 
7698 	/* plugin version (for SHOW PLUGINS) */
7699 	/* unsigned int */
7700 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7701 
7702 	/* struct st_mysql_show_var* */
7703 	STRUCT_FLD(status_vars, NULL),
7704 
7705 	/* struct st_mysql_sys_var** */
7706 	STRUCT_FLD(system_vars, NULL),
7707 
7708 	/* reserved for dependency checking */
7709 	/* void* */
7710 	STRUCT_FLD(__reserved1, NULL),
7711 
7712 	/* Plugin flags */
7713 	/* unsigned long */
7714 	STRUCT_FLD(flags, 0UL),
7715 };
7716 /**  SYS_FIELDS  ***************************************************/
7717 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FIELDS */
7718 static ST_FIELD_INFO	innodb_sys_fields_fields_info[] =
7719 {
7720 #define SYS_FIELD_INDEX_ID	0
7721 	{STRUCT_FLD(field_name,		"INDEX_ID"),
7722 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
7723 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
7724 	 STRUCT_FLD(value,		0),
7725 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7726 	 STRUCT_FLD(old_name,		""),
7727 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7728 
7729 #define SYS_FIELD_NAME		1
7730 	{STRUCT_FLD(field_name,		"NAME"),
7731 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7732 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7733 	 STRUCT_FLD(value,		0),
7734 	 STRUCT_FLD(field_flags,	0),
7735 	 STRUCT_FLD(old_name,		""),
7736 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7737 
7738 #define SYS_FIELD_POS		2
7739 	{STRUCT_FLD(field_name,		"POS"),
7740 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7741 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7742 	 STRUCT_FLD(value,		0),
7743 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7744 	 STRUCT_FLD(old_name,		""),
7745 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7746 
7747 	END_OF_ST_FIELD_INFO
7748 };
7749 
7750 /**********************************************************************//**
7751 Function to fill information_schema.innodb_sys_fields with information
7752 collected by scanning SYS_FIELDS table.
7753 @return 0 on success */
7754 static
7755 int
i_s_dict_fill_sys_fields(THD * thd,index_id_t index_id,dict_field_t * field,ulint pos,TABLE * table_to_fill)7756 i_s_dict_fill_sys_fields(
7757 /*=====================*/
7758 	THD*		thd,		/*!< in: thread */
7759 	index_id_t	index_id,	/*!< in: index id for the field */
7760 	dict_field_t*	field,		/*!< in: table */
7761 	ulint		pos,		/*!< in: Field position */
7762 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7763 {
7764 	Field**		fields;
7765 
7766 	DBUG_ENTER("i_s_dict_fill_sys_fields");
7767 
7768 	fields = table_to_fill->field;
7769 
7770 	OK(fields[SYS_FIELD_INDEX_ID]->store(index_id, true));
7771 
7772 	OK(field_store_string(fields[SYS_FIELD_NAME], field->name));
7773 
7774 	OK(fields[SYS_FIELD_POS]->store(pos, true));
7775 
7776 	OK(schema_table_store_record(thd, table_to_fill));
7777 
7778 	DBUG_RETURN(0);
7779 }
7780 /*******************************************************************//**
7781 Function to go through each record in SYS_FIELDS table, and fill the
7782 information_schema.innodb_sys_fields table with related index field
7783 information
7784 @return 0 on success */
7785 static
7786 int
i_s_sys_fields_fill_table(THD * thd,TABLE_LIST * tables,Item *)7787 i_s_sys_fields_fill_table(
7788 /*======================*/
7789 	THD*		thd,	/*!< in: thread */
7790 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
7791 	Item*		)	/*!< in: condition (not used) */
7792 {
7793 	btr_pcur_t	pcur;
7794 	const rec_t*	rec;
7795 	mem_heap_t*	heap;
7796 	index_id_t	last_id;
7797 	mtr_t		mtr;
7798 
7799 	DBUG_ENTER("i_s_sys_fields_fill_table");
7800 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
7801 
7802 	/* deny access to user without PROCESS_ACL privilege */
7803 	if (check_global_access(thd, PROCESS_ACL)) {
7804 
7805 		DBUG_RETURN(0);
7806 	}
7807 
7808 	heap = mem_heap_create(1000);
7809 	mutex_enter(&dict_sys->mutex);
7810 	mtr_start(&mtr);
7811 
7812 	/* will save last index id so that we know whether we move to
7813 	the next index. This is used to calculate prefix length */
7814 	last_id = 0;
7815 
7816 	rec = dict_startscan_system(&pcur, &mtr, SYS_FIELDS);
7817 
7818 	while (rec) {
7819 		ulint		pos;
7820 		const char*	err_msg;
7821 		index_id_t	index_id;
7822 		dict_field_t	field_rec;
7823 
7824 		/* Populate a dict_field_t structure with information from
7825 		a SYS_FIELDS row */
7826 		err_msg = dict_process_sys_fields_rec(heap, rec, &field_rec,
7827 						      &pos, &index_id, last_id);
7828 
7829 		mtr_commit(&mtr);
7830 		mutex_exit(&dict_sys->mutex);
7831 
7832 		if (!err_msg) {
7833 			i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
7834 						 pos, tables->table);
7835 			last_id = index_id;
7836 		} else {
7837 			push_warning_printf(thd, Sql_condition::SL_WARNING,
7838 					    ER_CANT_FIND_SYSTEM_REC, "%s",
7839 					    err_msg);
7840 		}
7841 
7842 		mem_heap_empty(heap);
7843 
7844 		/* Get the next record */
7845 		mutex_enter(&dict_sys->mutex);
7846 		mtr_start(&mtr);
7847 		rec = dict_getnext_system(&pcur, &mtr);
7848 	}
7849 
7850 	mtr_commit(&mtr);
7851 	mutex_exit(&dict_sys->mutex);
7852 	mem_heap_free(heap);
7853 
7854 	DBUG_RETURN(0);
7855 }
7856 /*******************************************************************//**
7857 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_fields
7858 @return 0 on success */
7859 static
7860 int
innodb_sys_fields_init(void * p)7861 innodb_sys_fields_init(
7862 /*===================*/
7863 	void*   p)	/*!< in/out: table schema object */
7864 {
7865 	ST_SCHEMA_TABLE*	schema;
7866 
7867 	DBUG_ENTER("innodb_sys_field_init");
7868 
7869 	schema = (ST_SCHEMA_TABLE*) p;
7870 
7871 	schema->fields_info = innodb_sys_fields_fields_info;
7872 	schema->fill_table = i_s_sys_fields_fill_table;
7873 
7874 	DBUG_RETURN(0);
7875 }
7876 
7877 struct st_mysql_plugin	i_s_innodb_sys_fields =
7878 {
7879 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
7880 	/* int */
7881 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
7882 
7883 	/* pointer to type-specific plugin descriptor */
7884 	/* void* */
7885 	STRUCT_FLD(info, &i_s_info),
7886 
7887 	/* plugin name */
7888 	/* const char* */
7889 	STRUCT_FLD(name, "INNODB_SYS_FIELDS"),
7890 
7891 	/* plugin author (for SHOW PLUGINS) */
7892 	/* const char* */
7893 	STRUCT_FLD(author, plugin_author),
7894 
7895 	/* general descriptive text (for SHOW PLUGINS) */
7896 	/* const char* */
7897 	STRUCT_FLD(descr, "InnoDB SYS_FIELDS"),
7898 
7899 	/* the plugin license (PLUGIN_LICENSE_XXX) */
7900 	/* int */
7901 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
7902 
7903 	/* the function to invoke when plugin is loaded */
7904 	/* int (*)(void*); */
7905 	STRUCT_FLD(init, innodb_sys_fields_init),
7906 
7907 	/* the function to invoke when plugin is unloaded */
7908 	/* int (*)(void*); */
7909 	STRUCT_FLD(deinit, i_s_common_deinit),
7910 
7911 	/* plugin version (for SHOW PLUGINS) */
7912 	/* unsigned int */
7913 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
7914 
7915 	/* struct st_mysql_show_var* */
7916 	STRUCT_FLD(status_vars, NULL),
7917 
7918 	/* struct st_mysql_sys_var** */
7919 	STRUCT_FLD(system_vars, NULL),
7920 
7921 	/* reserved for dependency checking */
7922 	/* void* */
7923 	STRUCT_FLD(__reserved1, NULL),
7924 
7925 	/* Plugin flags */
7926 	/* unsigned long */
7927 	STRUCT_FLD(flags, 0UL),
7928 };
7929 
7930 /**  SYS_FOREIGN        ********************************************/
7931 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN */
7932 static ST_FIELD_INFO	innodb_sys_foreign_fields_info[] =
7933 {
7934 #define SYS_FOREIGN_ID		0
7935 	{STRUCT_FLD(field_name,		"ID"),
7936 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7937 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7938 	 STRUCT_FLD(value,		0),
7939 	 STRUCT_FLD(field_flags,	0),
7940 	 STRUCT_FLD(old_name,		""),
7941 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7942 
7943 #define SYS_FOREIGN_FOR_NAME	1
7944 	{STRUCT_FLD(field_name,		"FOR_NAME"),
7945 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7946 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7947 	 STRUCT_FLD(value,		0),
7948 	 STRUCT_FLD(field_flags,	0),
7949 	 STRUCT_FLD(old_name,		""),
7950 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7951 
7952 #define SYS_FOREIGN_REF_NAME	2
7953 	{STRUCT_FLD(field_name,		"REF_NAME"),
7954 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
7955 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
7956 	 STRUCT_FLD(value,		0),
7957 	 STRUCT_FLD(field_flags,	0),
7958 	 STRUCT_FLD(old_name,		""),
7959 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7960 
7961 #define SYS_FOREIGN_NUM_COL	3
7962 	{STRUCT_FLD(field_name,		"N_COLS"),
7963 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7964 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7965 	 STRUCT_FLD(value,		0),
7966 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7967 	 STRUCT_FLD(old_name,		""),
7968 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7969 
7970 #define SYS_FOREIGN_TYPE	4
7971 	{STRUCT_FLD(field_name,		"TYPE"),
7972 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
7973 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
7974 	 STRUCT_FLD(value,		0),
7975 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
7976 	 STRUCT_FLD(old_name,		""),
7977 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
7978 
7979 	END_OF_ST_FIELD_INFO
7980 };
7981 
7982 /**********************************************************************//**
7983 Function to fill information_schema.innodb_sys_foreign with information
7984 collected by scanning SYS_FOREIGN table.
7985 @return 0 on success */
7986 static
7987 int
i_s_dict_fill_sys_foreign(THD * thd,dict_foreign_t * foreign,TABLE * table_to_fill)7988 i_s_dict_fill_sys_foreign(
7989 /*======================*/
7990 	THD*		thd,		/*!< in: thread */
7991 	dict_foreign_t*	foreign,	/*!< in: table */
7992 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
7993 {
7994 	Field**		fields;
7995 
7996 	DBUG_ENTER("i_s_dict_fill_sys_foreign");
7997 
7998 	fields = table_to_fill->field;
7999 
8000 	OK(field_store_string(fields[SYS_FOREIGN_ID], foreign->id));
8001 
8002 	OK(field_store_string(fields[SYS_FOREIGN_FOR_NAME],
8003 			      foreign->foreign_table_name));
8004 
8005 	OK(field_store_string(fields[SYS_FOREIGN_REF_NAME],
8006 			      foreign->referenced_table_name));
8007 
8008 	OK(fields[SYS_FOREIGN_NUM_COL]->store(foreign->n_fields));
8009 
8010 	OK(fields[SYS_FOREIGN_TYPE]->store(foreign->type));
8011 
8012 	OK(schema_table_store_record(thd, table_to_fill));
8013 
8014 	DBUG_RETURN(0);
8015 }
8016 
8017 /*******************************************************************//**
8018 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign table. Loop
8019 through each record in SYS_FOREIGN, and extract the foreign key
8020 information.
8021 @return 0 on success */
8022 static
8023 int
i_s_sys_foreign_fill_table(THD * thd,TABLE_LIST * tables,Item *)8024 i_s_sys_foreign_fill_table(
8025 /*=======================*/
8026 	THD*		thd,	/*!< in: thread */
8027 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
8028 	Item*		)	/*!< in: condition (not used) */
8029 {
8030 	btr_pcur_t	pcur;
8031 	const rec_t*	rec;
8032 	mem_heap_t*	heap;
8033 	mtr_t		mtr;
8034 
8035 	DBUG_ENTER("i_s_sys_foreign_fill_table");
8036 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8037 
8038 	/* deny access to user without PROCESS_ACL privilege */
8039 	if (check_global_access(thd, PROCESS_ACL)) {
8040 
8041 		DBUG_RETURN(0);
8042 	}
8043 
8044 	heap = mem_heap_create(1000);
8045 	mutex_enter(&dict_sys->mutex);
8046 	mtr_start(&mtr);
8047 
8048 	rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
8049 
8050 	while (rec) {
8051 		const char*	err_msg;
8052 		dict_foreign_t	foreign_rec;
8053 
8054 		/* Populate a dict_foreign_t structure with information from
8055 		a SYS_FOREIGN row */
8056 		err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
8057 
8058 		mtr_commit(&mtr);
8059 		mutex_exit(&dict_sys->mutex);
8060 
8061 		if (!err_msg) {
8062 			i_s_dict_fill_sys_foreign(thd, &foreign_rec,
8063 						 tables->table);
8064 		} else {
8065 			push_warning_printf(thd, Sql_condition::SL_WARNING,
8066 					    ER_CANT_FIND_SYSTEM_REC, "%s",
8067 					    err_msg);
8068 		}
8069 
8070 		mem_heap_empty(heap);
8071 
8072 		/* Get the next record */
8073 		mtr_start(&mtr);
8074 		mutex_enter(&dict_sys->mutex);
8075 		rec = dict_getnext_system(&pcur, &mtr);
8076 	}
8077 
8078 	mtr_commit(&mtr);
8079 	mutex_exit(&dict_sys->mutex);
8080 	mem_heap_free(heap);
8081 
8082 	DBUG_RETURN(0);
8083 }
8084 
8085 /*******************************************************************//**
8086 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign
8087 @return 0 on success */
8088 static
8089 int
innodb_sys_foreign_init(void * p)8090 innodb_sys_foreign_init(
8091 /*====================*/
8092 	void*   p)	/*!< in/out: table schema object */
8093 {
8094 	ST_SCHEMA_TABLE*	schema;
8095 
8096 	DBUG_ENTER("innodb_sys_foreign_init");
8097 
8098 	schema = (ST_SCHEMA_TABLE*) p;
8099 
8100 	schema->fields_info = innodb_sys_foreign_fields_info;
8101 	schema->fill_table = i_s_sys_foreign_fill_table;
8102 
8103 	DBUG_RETURN(0);
8104 }
8105 
8106 struct st_mysql_plugin	i_s_innodb_sys_foreign =
8107 {
8108 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
8109 	/* int */
8110 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8111 
8112 	/* pointer to type-specific plugin descriptor */
8113 	/* void* */
8114 	STRUCT_FLD(info, &i_s_info),
8115 
8116 	/* plugin name */
8117 	/* const char* */
8118 	STRUCT_FLD(name, "INNODB_SYS_FOREIGN"),
8119 
8120 	/* plugin author (for SHOW PLUGINS) */
8121 	/* const char* */
8122 	STRUCT_FLD(author, plugin_author),
8123 
8124 	/* general descriptive text (for SHOW PLUGINS) */
8125 	/* const char* */
8126 	STRUCT_FLD(descr, "InnoDB SYS_FOREIGN"),
8127 
8128 	/* the plugin license (PLUGIN_LICENSE_XXX) */
8129 	/* int */
8130 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8131 
8132 	/* the function to invoke when plugin is loaded */
8133 	/* int (*)(void*); */
8134 	STRUCT_FLD(init, innodb_sys_foreign_init),
8135 
8136 	/* the function to invoke when plugin is unloaded */
8137 	/* int (*)(void*); */
8138 	STRUCT_FLD(deinit, i_s_common_deinit),
8139 
8140 	/* plugin version (for SHOW PLUGINS) */
8141 	/* unsigned int */
8142 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
8143 
8144 	/* struct st_mysql_show_var* */
8145 	STRUCT_FLD(status_vars, NULL),
8146 
8147 	/* struct st_mysql_sys_var** */
8148 	STRUCT_FLD(system_vars, NULL),
8149 
8150 	/* reserved for dependency checking */
8151 	/* void* */
8152 	STRUCT_FLD(__reserved1, NULL),
8153 
8154 	/* Plugin flags */
8155 	/* unsigned long */
8156 	STRUCT_FLD(flags, 0UL),
8157 };
8158 
8159 /**  SYS_FOREIGN_COLS   ********************************************/
8160 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS */
8161 static ST_FIELD_INFO	innodb_sys_foreign_cols_fields_info[] =
8162 {
8163 #define SYS_FOREIGN_COL_ID		0
8164 	{STRUCT_FLD(field_name,		"ID"),
8165 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
8166 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8167 	 STRUCT_FLD(value,		0),
8168 	 STRUCT_FLD(field_flags,	0),
8169 	 STRUCT_FLD(old_name,		""),
8170 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8171 
8172 #define SYS_FOREIGN_COL_FOR_NAME	1
8173 	{STRUCT_FLD(field_name,		"FOR_COL_NAME"),
8174 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
8175 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8176 	 STRUCT_FLD(value,		0),
8177 	 STRUCT_FLD(field_flags,	0),
8178 	 STRUCT_FLD(old_name,		""),
8179 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8180 
8181 #define SYS_FOREIGN_COL_REF_NAME	2
8182 	{STRUCT_FLD(field_name,		"REF_COL_NAME"),
8183 	 STRUCT_FLD(field_length,	NAME_LEN + 1),
8184 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8185 	 STRUCT_FLD(value,		0),
8186 	 STRUCT_FLD(field_flags,	0),
8187 	 STRUCT_FLD(old_name,		""),
8188 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8189 
8190 #define SYS_FOREIGN_COL_POS		3
8191 	{STRUCT_FLD(field_name,		"POS"),
8192 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8193 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8194 	 STRUCT_FLD(value,		0),
8195 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8196 	 STRUCT_FLD(old_name,		""),
8197 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8198 
8199 	END_OF_ST_FIELD_INFO
8200 };
8201 
8202 /**********************************************************************//**
8203 Function to fill information_schema.innodb_sys_foreign_cols with information
8204 collected by scanning SYS_FOREIGN_COLS table.
8205 @return 0 on success */
8206 static
8207 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)8208 i_s_dict_fill_sys_foreign_cols(
8209 /*==========================*/
8210 	THD*		thd,		/*!< in: thread */
8211 	const char*	name,		/*!< in: foreign key constraint name */
8212 	const char*	for_col_name,	/*!< in: referencing column name*/
8213 	const char*	ref_col_name,	/*!< in: referenced column
8214 					name */
8215 	ulint		pos,		/*!< in: column position */
8216 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
8217 {
8218 	Field**		fields;
8219 
8220 	DBUG_ENTER("i_s_dict_fill_sys_foreign_cols");
8221 
8222 	fields = table_to_fill->field;
8223 
8224 	OK(field_store_string(fields[SYS_FOREIGN_COL_ID], name));
8225 
8226 	OK(field_store_string(fields[SYS_FOREIGN_COL_FOR_NAME], for_col_name));
8227 
8228 	OK(field_store_string(fields[SYS_FOREIGN_COL_REF_NAME], ref_col_name));
8229 
8230 	OK(fields[SYS_FOREIGN_COL_POS]->store(pos, true));
8231 
8232 	OK(schema_table_store_record(thd, table_to_fill));
8233 
8234 	DBUG_RETURN(0);
8235 }
8236 /*******************************************************************//**
8237 Function to populate INFORMATION_SCHEMA.innodb_sys_foreign_cols table. Loop
8238 through each record in SYS_FOREIGN_COLS, and extract the foreign key column
8239 information and fill the INFORMATION_SCHEMA.innodb_sys_foreign_cols table.
8240 @return 0 on success */
8241 static
8242 int
i_s_sys_foreign_cols_fill_table(THD * thd,TABLE_LIST * tables,Item *)8243 i_s_sys_foreign_cols_fill_table(
8244 /*============================*/
8245 	THD*		thd,	/*!< in: thread */
8246 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
8247 	Item*		)	/*!< in: condition (not used) */
8248 {
8249 	btr_pcur_t	pcur;
8250 	const rec_t*	rec;
8251 	mem_heap_t*	heap;
8252 	mtr_t		mtr;
8253 
8254 	DBUG_ENTER("i_s_sys_foreign_cols_fill_table");
8255 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8256 
8257 	/* deny access to user without PROCESS_ACL privilege */
8258 	if (check_global_access(thd, PROCESS_ACL)) {
8259 		DBUG_RETURN(0);
8260 	}
8261 
8262 	heap = mem_heap_create(1000);
8263 	mutex_enter(&dict_sys->mutex);
8264 	mtr_start(&mtr);
8265 
8266 	rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
8267 
8268 	while (rec) {
8269 		const char*	err_msg;
8270 		const char*	name;
8271 		const char*	for_col_name;
8272 		const char*	ref_col_name;
8273 		ulint		pos;
8274 
8275 		/* Extract necessary information from a SYS_FOREIGN_COLS row */
8276 		err_msg = dict_process_sys_foreign_col_rec(
8277 			heap, rec, &name, &for_col_name, &ref_col_name, &pos);
8278 
8279 		mtr_commit(&mtr);
8280 		mutex_exit(&dict_sys->mutex);
8281 
8282 		if (!err_msg) {
8283 			i_s_dict_fill_sys_foreign_cols(
8284 				thd, name, for_col_name, ref_col_name, pos,
8285 				tables->table);
8286 		} else {
8287 			push_warning_printf(thd, Sql_condition::SL_WARNING,
8288 					    ER_CANT_FIND_SYSTEM_REC, "%s",
8289 					    err_msg);
8290 		}
8291 
8292 		mem_heap_empty(heap);
8293 
8294 		/* Get the next record */
8295 		mutex_enter(&dict_sys->mutex);
8296 		mtr_start(&mtr);
8297 		rec = dict_getnext_system(&pcur, &mtr);
8298 	}
8299 
8300 	mtr_commit(&mtr);
8301 	mutex_exit(&dict_sys->mutex);
8302 	mem_heap_free(heap);
8303 
8304 	DBUG_RETURN(0);
8305 }
8306 /*******************************************************************//**
8307 Bind the dynamic table INFORMATION_SCHEMA.innodb_sys_foreign_cols
8308 @return 0 on success */
8309 static
8310 int
innodb_sys_foreign_cols_init(void * p)8311 innodb_sys_foreign_cols_init(
8312 /*========================*/
8313 	void*	p)	/*!< in/out: table schema object */
8314 {
8315 	ST_SCHEMA_TABLE*	schema;
8316 
8317 	DBUG_ENTER("innodb_sys_foreign_cols_init");
8318 
8319 	schema = (ST_SCHEMA_TABLE*) p;
8320 
8321 	schema->fields_info = innodb_sys_foreign_cols_fields_info;
8322 	schema->fill_table = i_s_sys_foreign_cols_fill_table;
8323 
8324 	DBUG_RETURN(0);
8325 }
8326 
8327 struct st_mysql_plugin	i_s_innodb_sys_foreign_cols =
8328 {
8329 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
8330 	/* int */
8331 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8332 
8333 	/* pointer to type-specific plugin descriptor */
8334 	/* void* */
8335 	STRUCT_FLD(info, &i_s_info),
8336 
8337 	/* plugin name */
8338 	/* const char* */
8339 	STRUCT_FLD(name, "INNODB_SYS_FOREIGN_COLS"),
8340 
8341 	/* plugin author (for SHOW PLUGINS) */
8342 	/* const char* */
8343 	STRUCT_FLD(author, plugin_author),
8344 
8345 	/* general descriptive text (for SHOW PLUGINS) */
8346 	/* const char* */
8347 	STRUCT_FLD(descr, "InnoDB SYS_FOREIGN_COLS"),
8348 
8349 	/* the plugin license (PLUGIN_LICENSE_XXX) */
8350 	/* int */
8351 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8352 
8353 	/* the function to invoke when plugin is loaded */
8354 	/* int (*)(void*); */
8355 	STRUCT_FLD(init, innodb_sys_foreign_cols_init),
8356 
8357 	/* the function to invoke when plugin is unloaded */
8358 	/* int (*)(void*); */
8359 	STRUCT_FLD(deinit, i_s_common_deinit),
8360 
8361 	/* plugin version (for SHOW PLUGINS) */
8362 	/* unsigned int */
8363 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
8364 
8365 	/* struct st_mysql_show_var* */
8366 	STRUCT_FLD(status_vars, NULL),
8367 
8368 	/* struct st_mysql_sys_var** */
8369 	STRUCT_FLD(system_vars, NULL),
8370 
8371 	/* reserved for dependency checking */
8372 	/* void* */
8373 	STRUCT_FLD(__reserved1, NULL),
8374 
8375 	/* Plugin flags */
8376 	/* unsigned long */
8377 	STRUCT_FLD(flags, 0UL),
8378 };
8379 
8380 /**  SYS_TABLESPACES    ********************************************/
8381 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES */
8382 static ST_FIELD_INFO	innodb_sys_tablespaces_fields_info[] =
8383 {
8384 #define SYS_TABLESPACES_SPACE		0
8385 	{STRUCT_FLD(field_name,		"SPACE"),
8386 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8387 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8388 	 STRUCT_FLD(value,		0),
8389 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8390 	 STRUCT_FLD(old_name,		""),
8391 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8392 
8393 #define SYS_TABLESPACES_NAME		1
8394 	{STRUCT_FLD(field_name,		"NAME"),
8395 	 STRUCT_FLD(field_length,	MAX_FULL_NAME_LEN + 1),
8396 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8397 	 STRUCT_FLD(value,		0),
8398 	 STRUCT_FLD(field_flags,	0),
8399 	 STRUCT_FLD(old_name,		""),
8400 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8401 
8402 #define SYS_TABLESPACES_FLAGS		2
8403 	{STRUCT_FLD(field_name,		"FLAG"),
8404 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8405 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8406 	 STRUCT_FLD(value,		0),
8407 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8408 	 STRUCT_FLD(old_name,		""),
8409 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8410 
8411 #define SYS_TABLESPACES_FILE_FORMAT	3
8412 	{STRUCT_FLD(field_name,		"FILE_FORMAT"),
8413 	 STRUCT_FLD(field_length,	10),
8414 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8415 	 STRUCT_FLD(value,		0),
8416 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
8417 	 STRUCT_FLD(old_name,		""),
8418 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8419 
8420 #define SYS_TABLESPACES_ROW_FORMAT	4
8421 	{STRUCT_FLD(field_name,		"ROW_FORMAT"),
8422 	 STRUCT_FLD(field_length,	22),
8423 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8424 	 STRUCT_FLD(value,		0),
8425 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
8426 	 STRUCT_FLD(old_name,		""),
8427 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8428 
8429 #define SYS_TABLESPACES_PAGE_SIZE	5
8430 	{STRUCT_FLD(field_name,		"PAGE_SIZE"),
8431 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8432 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8433 	 STRUCT_FLD(value,		0),
8434 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8435 	 STRUCT_FLD(old_name,		""),
8436 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8437 
8438 #define SYS_TABLESPACES_ZIP_PAGE_SIZE	6
8439 	{STRUCT_FLD(field_name,		"ZIP_PAGE_SIZE"),
8440 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8441 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8442 	 STRUCT_FLD(value,		0),
8443 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8444 	 STRUCT_FLD(old_name,		""),
8445 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8446 
8447 #define SYS_TABLESPACES_SPACE_TYPE	7
8448 	{STRUCT_FLD(field_name,		"SPACE_TYPE"),
8449 	 STRUCT_FLD(field_length,	10),
8450 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8451 	 STRUCT_FLD(value,		0),
8452 	 STRUCT_FLD(field_flags,	MY_I_S_MAYBE_NULL),
8453 	 STRUCT_FLD(old_name,		""),
8454 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8455 
8456 #define SYS_TABLESPACES_FS_BLOCK_SIZE	8
8457 	{STRUCT_FLD(field_name,		"FS_BLOCK_SIZE"),
8458 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8459 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8460 	 STRUCT_FLD(value,		0),
8461 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8462 	 STRUCT_FLD(old_name,		""),
8463 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8464 
8465 #define SYS_TABLESPACES_FILE_SIZE	9
8466 	{STRUCT_FLD(field_name,		"FILE_SIZE"),
8467 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
8468 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
8469 	 STRUCT_FLD(value,		0),
8470 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8471 	 STRUCT_FLD(old_name,		""),
8472 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8473 
8474 #define SYS_TABLESPACES_ALLOC_SIZE	10
8475 	{STRUCT_FLD(field_name,		"ALLOCATED_SIZE"),
8476 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
8477 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
8478 	 STRUCT_FLD(value,		0),
8479 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8480 	 STRUCT_FLD(old_name,           ""),
8481 	 STRUCT_FLD(open_method,        SKIP_OPEN_TABLE)},
8482 
8483 	END_OF_ST_FIELD_INFO
8484 
8485 };
8486 
8487 /**********************************************************************//**
8488 Function to fill INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES with information
8489 collected by scanning SYS_TABLESPACESS table.
8490 @return 0 on success */
8491 static
8492 int
i_s_dict_fill_sys_tablespaces(THD * thd,ulint space,const char * name,ulint flags,TABLE * table_to_fill)8493 i_s_dict_fill_sys_tablespaces(
8494 /*==========================*/
8495 	THD*		thd,		/*!< in: thread */
8496 	ulint		space,		/*!< in: space ID */
8497 	const char*	name,		/*!< in: tablespace name */
8498 	ulint		flags,		/*!< in: tablespace flags */
8499 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
8500 {
8501 	Field**		fields;
8502 	ulint		atomic_blobs = FSP_FLAGS_HAS_ATOMIC_BLOBS(flags);
8503 	bool		is_compressed = FSP_FLAGS_GET_ZIP_SSIZE(flags);
8504 	const char*	file_format;
8505 	const char*	row_format;
8506 	const page_size_t	page_size(flags);
8507 	const char*	space_type;
8508 
8509 	DBUG_ENTER("i_s_dict_fill_sys_tablespaces");
8510 
8511 	file_format = trx_sys_file_format_id_to_name(atomic_blobs);
8512 	if (is_system_tablespace(space)) {
8513 		row_format = "Compact or Redundant";
8514 	} else if (fsp_is_shared_tablespace(flags) && !is_compressed) {
8515 		file_format = "Any";
8516 		row_format = "Any";
8517 	} else if (is_compressed) {
8518 		row_format = "Compressed";
8519 	} else if (atomic_blobs) {
8520 		row_format = "Dynamic";
8521 	} else {
8522 		row_format = "Compact or Redundant";
8523 	}
8524 
8525 	if (is_system_tablespace(space)) {
8526 		space_type = "System";
8527 	} else if (fsp_is_shared_tablespace(flags)) {
8528 		space_type = "General";
8529 	} else  {
8530 		space_type = "Single";
8531 	}
8532 
8533 	fields = table_to_fill->field;
8534 
8535 	OK(fields[SYS_TABLESPACES_SPACE]->store(space, true));
8536 
8537 	OK(field_store_string(fields[SYS_TABLESPACES_NAME], name));
8538 
8539 	OK(fields[SYS_TABLESPACES_FLAGS]->store(flags, true));
8540 
8541 	OK(field_store_string(fields[SYS_TABLESPACES_FILE_FORMAT],
8542 			      file_format));
8543 
8544 	OK(field_store_string(fields[SYS_TABLESPACES_ROW_FORMAT], row_format));
8545 
8546 	OK(fields[SYS_TABLESPACES_PAGE_SIZE]->store(
8547 			univ_page_size.physical(), true));
8548 
8549 	OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store(
8550 				page_size.is_compressed()
8551 				? page_size.physical()
8552 				: 0, true));
8553 
8554 	OK(field_store_string(fields[SYS_TABLESPACES_SPACE_TYPE],
8555 			      space_type));
8556 
8557 	char*	filepath = NULL;
8558 	if (FSP_FLAGS_HAS_DATA_DIR(flags)
8559 	    || FSP_FLAGS_GET_SHARED(flags)) {
8560 		mutex_enter(&dict_sys->mutex);
8561 		filepath = dict_get_first_path(space);
8562 		mutex_exit(&dict_sys->mutex);
8563 	}
8564 
8565 	if (filepath == NULL) {
8566 		filepath = fil_make_filepath(NULL, name, IBD, false);
8567 	}
8568 
8569 	os_file_stat_t	stat;
8570 	os_file_size_t	file;
8571 
8572 	memset(&file, 0xff, sizeof(file));
8573 	memset(&stat, 0x0, sizeof(stat));
8574 
8575 	if (filepath != NULL) {
8576 
8577 		file = os_file_get_size(filepath);
8578 
8579 		/* Get the file system (or Volume) block size. */
8580 		dberr_t	err = os_file_get_status(filepath, &stat, false, false);
8581 
8582 		switch(err) {
8583 		case DB_FAIL:
8584 			ib::warn()
8585 				<< "File '" << filepath << "', failed to get "
8586 				<< "stats";
8587 			break;
8588 
8589 		case DB_SUCCESS:
8590 		case DB_NOT_FOUND:
8591 			break;
8592 
8593 		default:
8594 			ib::error()
8595 				<< "File '" << filepath << "' "
8596 				<< ut_strerr(err);
8597 			break;
8598 		}
8599 
8600 		ut_free(filepath);
8601 	}
8602 
8603 	if (file.m_total_size == static_cast<os_offset_t>(~0)) {
8604 		stat.block_size = 0;
8605 		file.m_total_size = 0;
8606 		file.m_alloc_size = 0;
8607 	}
8608 
8609 	OK(fields[SYS_TABLESPACES_FS_BLOCK_SIZE]->store(stat.block_size, true));
8610 
8611 	OK(fields[SYS_TABLESPACES_FILE_SIZE]->store(file.m_total_size, true));
8612 
8613 	OK(fields[SYS_TABLESPACES_ALLOC_SIZE]->store(file.m_alloc_size, true));
8614 
8615 	OK(schema_table_store_record(thd, table_to_fill));
8616 
8617 	DBUG_RETURN(0);
8618 }
8619 
8620 /*******************************************************************//**
8621 Function to populate INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
8622 Loop through each record in SYS_TABLESPACES, and extract the column
8623 information and fill the INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES table.
8624 @return 0 on success */
8625 static
8626 int
i_s_sys_tablespaces_fill_table(THD * thd,TABLE_LIST * tables,Item *)8627 i_s_sys_tablespaces_fill_table(
8628 /*===========================*/
8629 	THD*		thd,	/*!< in: thread */
8630 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
8631 	Item*		)	/*!< in: condition (not used) */
8632 {
8633 	btr_pcur_t	pcur;
8634 	const rec_t*	rec;
8635 	mem_heap_t*	heap;
8636 	mtr_t		mtr;
8637 
8638 	DBUG_ENTER("i_s_sys_tablespaces_fill_table");
8639 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8640 
8641 	/* deny access to user without PROCESS_ACL privilege */
8642 	if (check_global_access(thd, PROCESS_ACL)) {
8643 		DBUG_RETURN(0);
8644 	}
8645 
8646 	heap = mem_heap_create(1000);
8647 	mutex_enter(&dict_sys->mutex);
8648 	mtr_start(&mtr);
8649 
8650 	for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
8651 	     rec != NULL;
8652 	     rec = dict_getnext_system(&pcur, &mtr)) {
8653 
8654 		const char*	err_msg;
8655 		ulint		space;
8656 		const char*	name;
8657 		ulint		flags;
8658 
8659 		/* Extract necessary information from a SYS_TABLESPACES row */
8660 		err_msg = dict_process_sys_tablespaces(
8661 			heap, rec, &space, &name, &flags);
8662 
8663 		mtr_commit(&mtr);
8664 		mutex_exit(&dict_sys->mutex);
8665 
8666 		if (!err_msg) {
8667 			i_s_dict_fill_sys_tablespaces(
8668 				thd, space, name, flags,
8669 				tables->table);
8670 		} else {
8671 			push_warning_printf(thd, Sql_condition::SL_WARNING,
8672 					    ER_CANT_FIND_SYSTEM_REC, "%s",
8673 					    err_msg);
8674 		}
8675 
8676 		mem_heap_empty(heap);
8677 
8678 		/* Get the next record */
8679 		mutex_enter(&dict_sys->mutex);
8680 		mtr_start(&mtr);
8681 	}
8682 
8683 	mtr_commit(&mtr);
8684 	mutex_exit(&dict_sys->mutex);
8685 	mem_heap_free(heap);
8686 
8687 	DBUG_RETURN(0);
8688 }
8689 /*******************************************************************//**
8690 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
8691 @return 0 on success */
8692 static
8693 int
innodb_sys_tablespaces_init(void * p)8694 innodb_sys_tablespaces_init(
8695 /*========================*/
8696 	void*	p)	/*!< in/out: table schema object */
8697 {
8698 	ST_SCHEMA_TABLE*	schema;
8699 
8700 	DBUG_ENTER("innodb_sys_tablespaces_init");
8701 
8702 	schema = (ST_SCHEMA_TABLE*) p;
8703 
8704 	schema->fields_info = innodb_sys_tablespaces_fields_info;
8705 	schema->fill_table = i_s_sys_tablespaces_fill_table;
8706 
8707 	DBUG_RETURN(0);
8708 }
8709 
8710 struct st_mysql_plugin	i_s_innodb_sys_tablespaces =
8711 {
8712 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
8713 	/* int */
8714 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8715 
8716 	/* pointer to type-specific plugin descriptor */
8717 	/* void* */
8718 	STRUCT_FLD(info, &i_s_info),
8719 
8720 	/* plugin name */
8721 	/* const char* */
8722 	STRUCT_FLD(name, "INNODB_SYS_TABLESPACES"),
8723 
8724 	/* plugin author (for SHOW PLUGINS) */
8725 	/* const char* */
8726 	STRUCT_FLD(author, plugin_author),
8727 
8728 	/* general descriptive text (for SHOW PLUGINS) */
8729 	/* const char* */
8730 	STRUCT_FLD(descr, "InnoDB SYS_TABLESPACES"),
8731 
8732 	/* the plugin license (PLUGIN_LICENSE_XXX) */
8733 	/* int */
8734 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8735 
8736 	/* the function to invoke when plugin is loaded */
8737 	/* int (*)(void*); */
8738 	STRUCT_FLD(init, innodb_sys_tablespaces_init),
8739 
8740 	/* the function to invoke when plugin is unloaded */
8741 	/* int (*)(void*); */
8742 	STRUCT_FLD(deinit, i_s_common_deinit),
8743 
8744 	/* plugin version (for SHOW PLUGINS) */
8745 	/* unsigned int */
8746 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
8747 
8748 	/* struct st_mysql_show_var* */
8749 	STRUCT_FLD(status_vars, NULL),
8750 
8751 	/* struct st_mysql_sys_var** */
8752 	STRUCT_FLD(system_vars, NULL),
8753 
8754 	/* reserved for dependency checking */
8755 	/* void* */
8756 	STRUCT_FLD(__reserved1, NULL),
8757 
8758 	/* Plugin flags */
8759 	/* unsigned long */
8760 	STRUCT_FLD(flags, 0UL),
8761 };
8762 
8763 /**  SYS_DATAFILES  ************************************************/
8764 /* Fields of the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES */
8765 static ST_FIELD_INFO	innodb_sys_datafiles_fields_info[] =
8766 {
8767 #define SYS_DATAFILES_SPACE		0
8768 	{STRUCT_FLD(field_name,		"SPACE"),
8769 	 STRUCT_FLD(field_length,	MY_INT32_NUM_DECIMAL_DIGITS),
8770 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONG),
8771 	 STRUCT_FLD(value,		0),
8772 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
8773 	 STRUCT_FLD(old_name,		""),
8774 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8775 
8776 #define SYS_DATAFILES_PATH		1
8777 	{STRUCT_FLD(field_name,		"PATH"),
8778 	 STRUCT_FLD(field_length,	OS_FILE_MAX_PATH),
8779 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
8780 	 STRUCT_FLD(value,		0),
8781 	 STRUCT_FLD(field_flags,	0),
8782 	 STRUCT_FLD(old_name,		""),
8783 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
8784 
8785 	END_OF_ST_FIELD_INFO
8786 };
8787 
8788 /**********************************************************************//**
8789 Function to fill INFORMATION_SCHEMA.INNODB_SYS_DATAFILES with information
8790 collected by scanning SYS_DATAFILESS table.
8791 @return 0 on success */
8792 static
8793 int
i_s_dict_fill_sys_datafiles(THD * thd,ulint space,const char * path,TABLE * table_to_fill)8794 i_s_dict_fill_sys_datafiles(
8795 /*========================*/
8796 	THD*		thd,		/*!< in: thread */
8797 	ulint		space,		/*!< in: space ID */
8798 	const char*	path,		/*!< in: absolute path */
8799 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
8800 {
8801 	Field**		fields;
8802 
8803 	DBUG_ENTER("i_s_dict_fill_sys_datafiles");
8804 
8805 	fields = table_to_fill->field;
8806 
8807 	OK(field_store_ulint(fields[SYS_DATAFILES_SPACE], space));
8808 
8809 	OK(field_store_string(fields[SYS_DATAFILES_PATH], path));
8810 
8811 	OK(schema_table_store_record(thd, table_to_fill));
8812 
8813 	DBUG_RETURN(0);
8814 }
8815 /*******************************************************************//**
8816 Function to populate INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8817 Loop through each record in SYS_DATAFILES, and extract the column
8818 information and fill the INFORMATION_SCHEMA.INNODB_SYS_DATAFILES table.
8819 @return 0 on success */
8820 static
8821 int
i_s_sys_datafiles_fill_table(THD * thd,TABLE_LIST * tables,Item *)8822 i_s_sys_datafiles_fill_table(
8823 /*=========================*/
8824 	THD*		thd,	/*!< in: thread */
8825 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
8826 	Item*		)	/*!< in: condition (not used) */
8827 {
8828 	btr_pcur_t	pcur;
8829 	const rec_t*	rec;
8830 	mem_heap_t*	heap;
8831 	mtr_t		mtr;
8832 
8833 	DBUG_ENTER("i_s_sys_datafiles_fill_table");
8834 	RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
8835 
8836 	/* deny access to user without PROCESS_ACL privilege */
8837 	if (check_global_access(thd, PROCESS_ACL)) {
8838 		DBUG_RETURN(0);
8839 	}
8840 
8841 	heap = mem_heap_create(1000);
8842 	mutex_enter(&dict_sys->mutex);
8843 	mtr_start(&mtr);
8844 
8845 	rec = dict_startscan_system(&pcur, &mtr, SYS_DATAFILES);
8846 
8847 	while (rec) {
8848 		const char*	err_msg;
8849 		ulint		space;
8850 		const char*	path;
8851 
8852 		/* Extract necessary information from a SYS_DATAFILES row */
8853 		err_msg = dict_process_sys_datafiles(
8854 			heap, rec, &space, &path);
8855 
8856 		mtr_commit(&mtr);
8857 		mutex_exit(&dict_sys->mutex);
8858 
8859 		if (!err_msg) {
8860 			i_s_dict_fill_sys_datafiles(
8861 				thd, space, path, tables->table);
8862 		} else {
8863 			push_warning_printf(thd, Sql_condition::SL_WARNING,
8864 					    ER_CANT_FIND_SYSTEM_REC, "%s",
8865 					    err_msg);
8866 		}
8867 
8868 		mem_heap_empty(heap);
8869 
8870 		/* Get the next record */
8871 		mutex_enter(&dict_sys->mutex);
8872 		mtr_start(&mtr);
8873 		rec = dict_getnext_system(&pcur, &mtr);
8874 	}
8875 
8876 	mtr_commit(&mtr);
8877 	mutex_exit(&dict_sys->mutex);
8878 	mem_heap_free(heap);
8879 
8880 	DBUG_RETURN(0);
8881 }
8882 /*******************************************************************//**
8883 Bind the dynamic table INFORMATION_SCHEMA.INNODB_SYS_DATAFILES
8884 @return 0 on success */
8885 static
8886 int
innodb_sys_datafiles_init(void * p)8887 innodb_sys_datafiles_init(
8888 /*======================*/
8889 	void*	p)	/*!< in/out: table schema object */
8890 {
8891 	ST_SCHEMA_TABLE*	schema;
8892 
8893 	DBUG_ENTER("innodb_sys_datafiles_init");
8894 
8895 	schema = (ST_SCHEMA_TABLE*) p;
8896 
8897 	schema->fields_info = innodb_sys_datafiles_fields_info;
8898 	schema->fill_table = i_s_sys_datafiles_fill_table;
8899 
8900 	DBUG_RETURN(0);
8901 }
8902 
8903 struct st_mysql_plugin	i_s_innodb_sys_datafiles =
8904 {
8905 	/* the plugin type (a MYSQL_XXX_PLUGIN value) */
8906 	/* int */
8907 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
8908 
8909 	/* pointer to type-specific plugin descriptor */
8910 	/* void* */
8911 	STRUCT_FLD(info, &i_s_info),
8912 
8913 	/* plugin name */
8914 	/* const char* */
8915 	STRUCT_FLD(name, "INNODB_SYS_DATAFILES"),
8916 
8917 	/* plugin author (for SHOW PLUGINS) */
8918 	/* const char* */
8919 	STRUCT_FLD(author, plugin_author),
8920 
8921 	/* general descriptive text (for SHOW PLUGINS) */
8922 	/* const char* */
8923 	STRUCT_FLD(descr, "InnoDB SYS_DATAFILES"),
8924 
8925 	/* the plugin license (PLUGIN_LICENSE_XXX) */
8926 	/* int */
8927 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
8928 
8929 	/* the function to invoke when plugin is loaded */
8930 	/* int (*)(void*); */
8931 	STRUCT_FLD(init, innodb_sys_datafiles_init),
8932 
8933 	/* the function to invoke when plugin is unloaded */
8934 	/* int (*)(void*); */
8935 	STRUCT_FLD(deinit, i_s_common_deinit),
8936 
8937 	/* plugin version (for SHOW PLUGINS) */
8938 	/* unsigned int */
8939 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
8940 
8941 	/* struct st_mysql_show_var* */
8942 	STRUCT_FLD(status_vars, NULL),
8943 
8944 	/* struct st_mysql_sys_var** */
8945 	STRUCT_FLD(system_vars, NULL),
8946 
8947 	/* reserved for dependency checking */
8948 	/* void* */
8949 	STRUCT_FLD(__reserved1, NULL),
8950 
8951 	/* Plugin flags */
8952 	/* unsigned long */
8953 	STRUCT_FLD(flags, 0UL),
8954 };
8955 
8956 /** Fill handlerton based INFORMATION_SCHEMA.FILES table.
8957 @param[in,out]	thd	thread/connection descriptor
8958 @param[in,out]	tables	information schema tables to fill
8959 @retval 0 for success
8960 @retval HA_ERR_OUT_OF_MEM when running out of memory
8961 @return nonzero for failure */
8962 int
i_s_files_table_fill(THD * thd,TABLE_LIST * tables)8963 i_s_files_table_fill(
8964 	THD*		thd,
8965 	TABLE_LIST*	tables)
8966 {
8967 	TABLE*			table_to_fill	= tables->table;
8968 	Field**			fields		= table_to_fill->field;
8969 	/* Use this class so that if the OK() macro returns,
8970 	fil_space_release() is called. */
8971 	FilSpace		space;
8972 
8973 	DBUG_ENTER("i_s_files_table_fill");
8974 
8975 	/* Gather information reportable to information_schema.files
8976 	for the first or next file in fil_system. */
8977 	for (const fil_node_t* node = fil_node_next(NULL);
8978 	     node != NULL;
8979 	     node = fil_node_next(node)) {
8980 		const char*	type = "TABLESPACE";
8981 		const char*	space_name;
8982 		/** Buffer to build file-per-table tablespace names.
8983 		Even though a space_id is often stored in a ulint, it cannot
8984 		be larger than 1<<32-1, which is 10 numeric characters. */
8985 		char		file_per_table_name[
8986 			sizeof("innodb_file_per_table_1234567890")];
8987 		uintmax_t	avail_space;
8988 		ulint		extent_pages;
8989 		ulint		extend_pages;
8990 
8991 		space = node->space;
8992 		fil_type_t	purpose = space()->purpose;
8993 
8994 		switch (purpose) {
8995 		case FIL_TYPE_LOG:
8996 			/* Do not report REDO LOGs to I_S.FILES */
8997 			space = NULL;
8998 			continue;
8999 		case FIL_TYPE_TABLESPACE:
9000 			if (srv_is_undo_tablespace(space()->id)) {
9001 				type = "UNDO LOG";
9002 				break;
9003 			} /* else fall through for TABLESPACE */
9004 		case FIL_TYPE_IMPORT:
9005 			/* 'IMPORTING'is a status. The type is TABLESPACE. */
9006 			break;
9007 		case FIL_TYPE_TEMPORARY:
9008 			type = "TEMPORARY";
9009 			break;
9010 		};
9011 
9012 		page_size_t	page_size(space()->flags);
9013 
9014 		/* Single-table tablespaces are assigned to a schema. */
9015 		if (!is_predefined_tablespace(space()->id)
9016 		    && !FSP_FLAGS_GET_SHARED(space()->flags)) {
9017 			/* Their names will be like "test/t1" */
9018 			ut_ad(NULL != strchr(space()->name, '/'));
9019 
9020 			/* File-per-table tablespace names are generated
9021 			internally and certain non-file-system-allowed
9022 			characters are expanded which can make the space
9023 			name too long. In order to avoid that problem,
9024 			use a modified tablespace name.
9025 			Since we are not returning dbname and tablename,
9026 			the user must match the space_id to i_s_table.space
9027 			in order find the single table that is in it or the
9028 			schema it belongs to. */
9029 			ut_snprintf(
9030 				file_per_table_name,
9031 				sizeof(file_per_table_name),
9032 				"innodb_file_per_table_" ULINTPF,
9033 				space()->id);
9034 			space_name = file_per_table_name;
9035 		} else {
9036 			/* Only file-per-table space names contain '/'.
9037                         This is not file-per-table . */
9038 			ut_ad(NULL == strchr(space()->name, '/'));
9039 
9040 			space_name = space()->name;
9041 		}
9042 
9043 		init_fill_schema_files_row(table_to_fill);
9044 
9045 		OK(field_store_ulint(fields[IS_FILES_FILE_ID],
9046 				     space()->id));
9047 		OK(field_store_string(fields[IS_FILES_FILE_NAME],
9048 				      node->name));
9049 		OK(field_store_string(fields[IS_FILES_FILE_TYPE],
9050 				      type));
9051 		OK(field_store_string(fields[IS_FILES_TABLESPACE_NAME],
9052 				      space_name));
9053 		OK(field_store_string(fields[IS_FILES_ENGINE],
9054 				      "InnoDB"));
9055 		OK(field_store_ulint(fields[IS_FILES_FREE_EXTENTS],
9056 				     space()->free_len));
9057 
9058 		extent_pages = fsp_get_extent_size_in_pages(page_size);
9059 
9060 		OK(field_store_ulint(fields[IS_FILES_TOTAL_EXTENTS],
9061 				     space()->size_in_header / extent_pages));
9062 		OK(field_store_ulint(fields[IS_FILES_EXTENT_SIZE],
9063 				     extent_pages * page_size.physical()));
9064 		OK(field_store_ulint(fields[IS_FILES_INITIAL_SIZE],
9065 				     node->init_size * page_size.physical()));
9066 
9067 		if (node->max_size >= ULINT_MAX) {
9068 			fields[IS_FILES_MAXIMUM_SIZE]->set_null();
9069 		} else {
9070 			OK(field_store_ulint(fields[IS_FILES_MAXIMUM_SIZE],
9071 				node->max_size * page_size.physical()));
9072 		}
9073 		if (space()->id == srv_sys_space.space_id()) {
9074 			extend_pages = srv_sys_space.get_increment();
9075 		} else if (space()->id == srv_tmp_space.space_id()) {
9076 			extend_pages = srv_tmp_space.get_increment();
9077 		} else {
9078 			extend_pages = fsp_get_pages_to_extend_ibd(
9079 				page_size, node->size);
9080 		}
9081 
9082 		OK(field_store_ulint(fields[IS_FILES_AUTOEXTEND_SIZE],
9083 				     extend_pages * page_size.physical()));
9084 
9085 		avail_space = fsp_get_available_space_in_free_extents(space());
9086 		OK(field_store_ulint(fields[IS_FILES_DATA_FREE],
9087 				     static_cast<ulint>(avail_space * 1024)));
9088 		OK(field_store_string(fields[IS_FILES_STATUS],
9089 				      (purpose == FIL_TYPE_IMPORT)
9090 				      ? "IMPORTING" : "NORMAL"));
9091 
9092 		schema_table_store_record(thd, table_to_fill);
9093 		space = NULL;
9094 	}
9095 
9096 	DBUG_RETURN(0);
9097 }
9098