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