1 /*****************************************************************************
2 
3 Copyright (c) 2007, 2012, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2010-2012, Percona Inc. All Rights Reserved.
5 
6 This program is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free Software
8 Foundation; version 2 of the License.
9 
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17 
18 *****************************************************************************/
19 
20 #include <mysqld_error.h>
21 #include <sql_acl.h>				// PROCESS_ACL
22 
23 #include <m_ctype.h>
24 #include <hash.h>
25 #include <myisampack.h>
26 #include <mysys_err.h>
27 #include <my_sys.h>
28 #include "i_s.h"
29 #include <sql_plugin.h>
30 #include <mysql/innodb_priv.h>
31 
32 #include <read0i_s.h>
33 #include <trx0i_s.h>
34 #include "srv0start.h"	/* for srv_was_started */
35 #include <btr0pcur.h> /* btr_pcur_t */
36 #include <btr0sea.h> /* btr_search_sys */
37 #include <log0recv.h> /* recv_sys */
38 #include <fil0fil.h>
39 #include <dict0crea.h> /* for ZIP_DICT_MAX_* constants */
40 
41 /* for XTRADB_RSEG table */
42 #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
43 #include "trx0rseg.h" /* for trx_rseg_struct */
44 #include "trx0sys.h" /* for trx_sys */
45 
46 #define PLUGIN_AUTHOR "Percona Inc."
47 
48 #define OK(expr)		\
49 	if ((expr) != 0) {	\
50 		DBUG_RETURN(1);	\
51 	}
52 
53 #if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 &&	\
54 	!defined __INTEL_COMPILER && !defined __clang__
55 #define STRUCT_FLD(name, value)	name: value
56 #else
57 #define STRUCT_FLD(name, value)	value
58 #endif
59 
60 #define END_OF_ST_FIELD_INFO \
61 	{STRUCT_FLD(field_name,		NULL), \
62 	 STRUCT_FLD(field_length,	0), \
63 	 STRUCT_FLD(field_type,		MYSQL_TYPE_NULL), \
64 	 STRUCT_FLD(value,		0), \
65 	 STRUCT_FLD(field_flags,	0), \
66 	 STRUCT_FLD(old_name,		""), \
67 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)}
68 
69 
70 /*******************************************************************//**
71 Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
72 If the value is ULINT_UNDEFINED then the field it set to NULL.
73 @return	0 on success */
74 static
75 int
field_store_ulint(Field * field,ulint n)76 field_store_ulint(
77 /*==============*/
78 	Field*	field,	/*!< in/out: target field for storage */
79 	ulint	n)	/*!< in: value to store */
80 {
81 	int	ret;
82 
83 	if (n != ULINT_UNDEFINED) {
84 
85 		ret = field->store(n);
86 		field->set_notnull();
87 	} else {
88 
89 		ret = 0; /* success */
90 		field->set_null();
91 	}
92 
93 	return(ret);
94 }
95 
96 /*******************************************************************//**
97 Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
98 @return	0 on success */
99 static
100 int
field_store_string(Field * field,const char * str)101 field_store_string(
102 /*===============*/
103 	Field*		field,	/*!< in/out: target field for storage */
104 	const char*	str)	/*!< in: NUL-terminated utf-8 string,
105 				or NULL */
106 {
107 	int	ret;
108 
109 	if (str != NULL) {
110 
111 		ret = field->store(str, strlen(str),
112 				   system_charset_info);
113 		field->set_notnull();
114 	} else {
115 
116 		ret = 0; /* success */
117 		field->set_null();
118 	}
119 
120 	return(ret);
121 }
122 /** Auxiliary function to store (char*, len) value in MYSQL_TYPE_BLOB
123 field.
124 @return	0 on success */
125 static
126 int
field_store_blob(Field * field,const char * data,uint data_len)127 field_store_blob(
128 	Field*		field,		/*!< in/out: target field for storage */
129 	const char*	data,		/*!< in: pointer to data, or NULL */
130 	uint		data_len)	/*!< in: data length */
131 {
132 	int	ret;
133 
134 	if (data != NULL) {
135 		ret = field->store(data, data_len, system_charset_info);
136 		field->set_notnull();
137 	} else {
138 		ret = 0; /* success */
139 		field->set_null();
140 	}
141 
142 	return(ret);
143 }
144 
145 static
146 int
i_s_common_deinit(void * p)147 i_s_common_deinit(
148 /*==============*/
149 	void*	p)	/*!< in/out: table schema object */
150 {
151 	DBUG_ENTER("i_s_common_deinit");
152 
153 	/* Do nothing */
154 
155 	DBUG_RETURN(0);
156 }
157 
158 static ST_FIELD_INFO xtradb_read_view_fields_info[] =
159 {
160 #define READ_VIEW_LOW_LIMIT_NUMBER	0
161 	{STRUCT_FLD(field_name,		"READ_VIEW_LOW_LIMIT_TRX_NUMBER"),
162 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
163 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
164 	 STRUCT_FLD(value,		0),
165 	 STRUCT_FLD(field_flags,	0),
166 	 STRUCT_FLD(old_name,		""),
167 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
168 
169 #define READ_VIEW_UPPER_LIMIT_ID	1
170 	{STRUCT_FLD(field_name,		"READ_VIEW_UPPER_LIMIT_TRX_ID"),
171 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
172 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
173 	 STRUCT_FLD(value,		0),
174 	 STRUCT_FLD(field_flags,	0),
175 	 STRUCT_FLD(old_name,		""),
176 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
177 
178 #define READ_VIEW_LOW_LIMIT_ID		2
179 	{STRUCT_FLD(field_name,		"READ_VIEW_LOW_LIMIT_TRX_ID"),
180 
181 	 STRUCT_FLD(field_length,	TRX_ID_MAX_LEN + 1),
182 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
183 	 STRUCT_FLD(value,		0),
184 	 STRUCT_FLD(field_flags,	0),
185 	 STRUCT_FLD(old_name,		""),
186 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
187 
188 	END_OF_ST_FIELD_INFO
189 };
190 
xtradb_read_view_fill_table(THD * thd,TABLE_LIST * tables,Item *)191 static int xtradb_read_view_fill_table(THD* thd, TABLE_LIST* tables, Item*)
192 {
193 	Field**	fields;
194 	TABLE* table;
195 	char		trx_id[TRX_ID_MAX_LEN + 1];
196 
197 
198 	DBUG_ENTER("xtradb_read_view_fill_table");
199 
200 	/* deny access to non-superusers */
201 	if (check_global_access(thd, PROCESS_ACL)) {
202 
203 		DBUG_RETURN(0);
204 	}
205 
206 	table = tables->table;
207 	fields = table->field;
208 
209 	i_s_xtradb_read_view_t read_view;
210 
211 	if (read_fill_i_s_xtradb_read_view(&read_view) == NULL)
212 		DBUG_RETURN(0);
213 
214 	ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, read_view.low_limit_no);
215 	OK(field_store_string(fields[READ_VIEW_LOW_LIMIT_NUMBER], trx_id));
216 
217 	ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, read_view.up_limit_id);
218 	OK(field_store_string(fields[READ_VIEW_UPPER_LIMIT_ID], trx_id));
219 
220 	ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, read_view.low_limit_id);
221 	OK(field_store_string(fields[READ_VIEW_LOW_LIMIT_ID], trx_id));
222 
223 	OK(schema_table_store_record(thd, table));
224 
225 	DBUG_RETURN(0);
226 }
227 
228 
xtradb_read_view_init(void * p)229 static int xtradb_read_view_init(void* p)
230 {
231 	ST_SCHEMA_TABLE*	schema;
232 
233 	DBUG_ENTER("xtradb_read_view_init");
234 
235 	schema = (ST_SCHEMA_TABLE*) p;
236 
237 	schema->fields_info = xtradb_read_view_fields_info;
238 	schema->fill_table = xtradb_read_view_fill_table;
239 
240 	DBUG_RETURN(0);
241 }
242 
243 static struct st_mysql_information_schema i_s_info =
244 {
245 	MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
246 };
247 
248 struct st_mysql_plugin i_s_xtradb_read_view =
249 {
250 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
251 	STRUCT_FLD(info, &i_s_info),
252 	STRUCT_FLD(name, "XTRADB_READ_VIEW"),
253 	STRUCT_FLD(author, PLUGIN_AUTHOR),
254 	STRUCT_FLD(descr, "InnoDB Read View information"),
255 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
256 	STRUCT_FLD(init, xtradb_read_view_init),
257 	STRUCT_FLD(deinit, i_s_common_deinit),
258 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
259 	STRUCT_FLD(status_vars, NULL),
260 	STRUCT_FLD(system_vars, NULL),
261 	STRUCT_FLD(__reserved1, NULL),
262 	STRUCT_FLD(flags, 0UL),
263 };
264 
265 static ST_FIELD_INFO xtradb_internal_hash_tables_fields_info[] =
266 {
267 #define INT_HASH_TABLES_NAME		0
268 	{STRUCT_FLD(field_name,		"INTERNAL_HASH_TABLE_NAME"),
269 	 STRUCT_FLD(field_length,	100),
270 	 STRUCT_FLD(field_type,		MYSQL_TYPE_STRING),
271 	 STRUCT_FLD(value,		0),
272 	 STRUCT_FLD(field_flags,	0),
273 	 STRUCT_FLD(old_name,		""),
274 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
275 
276 #define INT_HASH_TABLES_TOTAL		1
277 	{STRUCT_FLD(field_name,		"TOTAL_MEMORY"),
278 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
279 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
280 	 STRUCT_FLD(value,		0),
281 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
282 	 STRUCT_FLD(old_name,		""),
283 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
284 
285 #define INT_HASH_TABLES_CONSTANT		2
286 	{STRUCT_FLD(field_name,		"CONSTANT_MEMORY"),
287 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
288 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
289 	 STRUCT_FLD(value,		0),
290 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
291 	 STRUCT_FLD(old_name,		""),
292 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
293 
294 #define INT_HASH_TABLES_VARIABLE		3
295 	{STRUCT_FLD(field_name,		"VARIABLE_MEMORY"),
296 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
297 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
298 	 STRUCT_FLD(value,		0),
299 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
300 	 STRUCT_FLD(old_name,		""),
301 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
302 
303 	END_OF_ST_FIELD_INFO
304 };
305 
xtradb_internal_hash_tables_fill_table(THD * thd,TABLE_LIST * tables,Item *)306 static int xtradb_internal_hash_tables_fill_table(THD* thd, TABLE_LIST* tables, Item*)
307 {
308 	Field**		fields;
309 	TABLE*		table;
310 
311 	DBUG_ENTER("xtradb_internal_hash_tables_fill_table");
312 
313 	/* deny access to non-superusers */
314 	if (check_global_access(thd, PROCESS_ACL)) {
315 
316 		DBUG_RETURN(0);
317 	}
318 
319 	table = tables->table;
320 	fields = table->field;
321 
322 	/* Calculate AHI constant and variable memory allocations */
323 
324 	ulong btr_search_sys_constant = btr_search_sys_constant_mem;
325 	os_rmb;
326 	ulong btr_search_sys_variable = btr_search_sys_variable_mem;
327 	size_t dict_sys_hash_size = dict_sys->hash_size;
328 	ulong dict_sys_size = dict_sys->size;
329 
330 	OK(field_store_string(fields[INT_HASH_TABLES_NAME],
331 			      "Adaptive hash index"));
332 	OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
333 			     btr_search_sys_variable + btr_search_sys_constant));
334 	OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
335 			     btr_search_sys_constant));
336 	OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
337 			     btr_search_sys_variable));
338 	OK(schema_table_store_record(thd, table));
339 
340 	{
341 	  OK(field_store_string(fields[INT_HASH_TABLES_NAME],
342 				"Page hash (buffer pool 0 only)"));
343 	  OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
344 			       (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t))));
345 	  OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
346 			       (ulong) (buf_pool_from_array(0)->page_hash->n_cells * sizeof(hash_cell_t))));
347 	  OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE], 0));
348 	  OK(schema_table_store_record(thd, table));
349 
350 	}
351 
352 	OK(field_store_string(fields[INT_HASH_TABLES_NAME],
353 			      "Dictionary Cache"));
354 	OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
355 			     dict_sys_hash_size + dict_sys_size));
356 	OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
357 			     dict_sys_hash_size));
358 	OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
359 			     dict_sys_size));
360 	OK(schema_table_store_record(thd, table));
361 
362 	{
363 	  OK(field_store_string(fields[INT_HASH_TABLES_NAME],
364 				"File system"));
365 	  OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
366 			       (ulong) (fil_system_hash_cells()
367 					* sizeof(hash_cell_t)
368 					+ fil_system_hash_nodes())));
369 	  OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
370 			       (ulong) (fil_system_hash_cells() * sizeof(hash_cell_t))));
371 	  OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
372 			       (ulong) fil_system_hash_nodes()));
373 	  OK(schema_table_store_record(thd, table));
374 
375 	}
376 
377 	{
378 	  ulint lock_sys_constant, lock_sys_variable;
379 
380 	  trx_i_s_get_lock_sys_memory_usage(&lock_sys_constant,
381 					    &lock_sys_variable);
382 
383 	  OK(field_store_string(fields[INT_HASH_TABLES_NAME], "Lock System"));
384 	  OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
385 			       lock_sys_constant + lock_sys_variable));
386 	  OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
387 			       lock_sys_constant));
388 	  OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
389 			       lock_sys_variable));
390 	  OK(schema_table_store_record(thd, table));
391 	}
392 
393 	if (recv_sys)
394 	{
395 	  ulint recv_sys_subtotal = ((recv_sys && recv_sys->addr_hash)
396 				     ? mem_heap_get_size(recv_sys->heap) : 0);
397 
398 	  OK(field_store_string(fields[INT_HASH_TABLES_NAME], "Recovery System"));
399 	  OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
400 			       ((recv_sys->addr_hash) ? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0) + recv_sys_subtotal));
401 	  OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
402 			       ((recv_sys->addr_hash) ? (recv_sys->addr_hash->n_cells * sizeof(hash_cell_t)) : 0)));
403 	  OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
404 			       recv_sys_subtotal));
405 	  OK(schema_table_store_record(thd, table));
406 	}
407 
408 	DBUG_RETURN(0);
409 }
410 
xtradb_internal_hash_tables_init(void * p)411 static int xtradb_internal_hash_tables_init(void* p)
412 {
413 	ST_SCHEMA_TABLE*	schema;
414 
415 	DBUG_ENTER("xtradb_internal_hash_tables_init");
416 
417 	schema = (ST_SCHEMA_TABLE*) p;
418 
419 	schema->fields_info = xtradb_internal_hash_tables_fields_info;
420 	schema->fill_table = xtradb_internal_hash_tables_fill_table;
421 
422 	DBUG_RETURN(0);
423 }
424 
425 struct st_mysql_plugin i_s_xtradb_internal_hash_tables =
426 {
427 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
428 	STRUCT_FLD(info, &i_s_info),
429 	STRUCT_FLD(name, "XTRADB_INTERNAL_HASH_TABLES"),
430 	STRUCT_FLD(author, PLUGIN_AUTHOR),
431 	STRUCT_FLD(descr, "InnoDB internal hash tables information"),
432 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
433 	STRUCT_FLD(init, xtradb_internal_hash_tables_init),
434 	STRUCT_FLD(deinit, i_s_common_deinit),
435 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
436 	STRUCT_FLD(status_vars, NULL),
437 	STRUCT_FLD(system_vars, NULL),
438 	STRUCT_FLD(__reserved1, NULL),
439 	STRUCT_FLD(flags, 0UL),
440 };
441 
442 
443 /***********************************************************************
444 */
445 static ST_FIELD_INFO	i_s_xtradb_rseg_fields_info[] =
446 {
447 	{STRUCT_FLD(field_name,		"rseg_id"),
448 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
449 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
450 	 STRUCT_FLD(value,		0),
451 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
452 	 STRUCT_FLD(old_name,		""),
453 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
454 
455 	{STRUCT_FLD(field_name,		"space_id"),
456 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
457 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
458 	 STRUCT_FLD(value,		0),
459 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
460 	 STRUCT_FLD(old_name,		""),
461 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
462 
463 	{STRUCT_FLD(field_name,		"physical_page_size"),
464 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
465 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
466 	 STRUCT_FLD(value,		0),
467 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
468 	 STRUCT_FLD(old_name,		""),
469 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
470 
471 	{STRUCT_FLD(field_name,		"logical_page_size"),
472 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
473 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
474 	 STRUCT_FLD(value,		0),
475 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
476 	 STRUCT_FLD(old_name,		""),
477 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
478 
479 	{STRUCT_FLD(field_name,		"is_compressed"),
480 	 STRUCT_FLD(field_length,	1),
481 	 STRUCT_FLD(field_type,		MYSQL_TYPE_TINY),
482 	 STRUCT_FLD(value,		0),
483 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
484 	 STRUCT_FLD(old_name,		""),
485 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
486 
487 	{STRUCT_FLD(field_name,		"page_no"),
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 	{STRUCT_FLD(field_name,		"max_size"),
496 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
497 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
498 	 STRUCT_FLD(value,		0),
499 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
500 	 STRUCT_FLD(old_name,		""),
501 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
502 
503 	{STRUCT_FLD(field_name,		"curr_size"),
504 	 STRUCT_FLD(field_length,	MY_INT64_NUM_DECIMAL_DIGITS),
505 	 STRUCT_FLD(field_type,		MYSQL_TYPE_LONGLONG),
506 	 STRUCT_FLD(value,		0),
507 	 STRUCT_FLD(field_flags,	MY_I_S_UNSIGNED),
508 	 STRUCT_FLD(old_name,		""),
509 	 STRUCT_FLD(open_method,	SKIP_OPEN_TABLE)},
510 
511 	END_OF_ST_FIELD_INFO
512 };
513 
514 static
515 int
i_s_xtradb_rseg_fill(THD * thd,TABLE_LIST * tables,Item *)516 i_s_xtradb_rseg_fill(
517 /*=================*/
518 	THD*		thd,	/* in: thread */
519 	TABLE_LIST*	tables,	/* in/out: tables to fill */
520 	Item*		)	/* in: condition (ignored) */
521 {
522 	TABLE*	table	= (TABLE *) tables->table;
523 	int	status	= 0;
524 	trx_rseg_t*	rseg;
525 
526 	DBUG_ENTER("i_s_xtradb_rseg_fill");
527 
528 	/* deny access to non-superusers */
529 	if (check_global_access(thd, PROCESS_ACL)) {
530 
531 		DBUG_RETURN(0);
532 	}
533 
534 	for(int i=0; i < TRX_SYS_N_RSEGS; i++)
535 	{
536 	  rseg = trx_sys->rseg_array[i];
537 	  if (!rseg)
538 	    continue;
539 
540 	  table->field[0]->store(rseg->id);
541 	  table->field[1]->store(rseg->space);
542 	  table->field[2]->store(rseg->page_size.physical());
543 	  table->field[3]->store(rseg->page_size.logical());
544 	  table->field[4]->store(rseg->page_size.is_compressed());
545 	  table->field[5]->store(rseg->page_no);
546 	  table->field[6]->store(rseg->max_size);
547 	  table->field[7]->store(rseg->curr_size);
548 
549 	  if (schema_table_store_record(thd, table)) {
550 	    status = 1;
551 	    break;
552 	  }
553 	}
554 
555 	DBUG_RETURN(status);
556 }
557 
558 static
559 int
i_s_xtradb_rseg_init(void * p)560 i_s_xtradb_rseg_init(
561 /*=================*/
562 			/* out: 0 on success */
563 	void*	p)	/* in/out: table schema object */
564 {
565 	DBUG_ENTER("i_s_xtradb_rseg_init");
566 	ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
567 
568 	schema->fields_info = i_s_xtradb_rseg_fields_info;
569 	schema->fill_table = i_s_xtradb_rseg_fill;
570 
571 	DBUG_RETURN(0);
572 }
573 
574 struct st_mysql_plugin	i_s_xtradb_rseg =
575 {
576 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
577 	STRUCT_FLD(info, &i_s_info),
578 	STRUCT_FLD(name, "XTRADB_RSEG"),
579 	STRUCT_FLD(author, PLUGIN_AUTHOR),
580 	STRUCT_FLD(descr, "InnoDB rollback segment information"),
581 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
582 	STRUCT_FLD(init, i_s_xtradb_rseg_init),
583 	STRUCT_FLD(deinit, i_s_common_deinit),
584 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
585 	STRUCT_FLD(status_vars, NULL),
586 	STRUCT_FLD(system_vars, NULL),
587 	STRUCT_FLD(__reserved1, NULL),
588 	STRUCT_FLD(flags, 0UL),
589 };
590 
591 
592 /************************************************************************/
593 enum zip_dict_field_type
594 {
595 	zip_dict_field_id,
596 	zip_dict_field_name,
597 	zip_dict_field_zip_dict
598 };
599 
600 static ST_FIELD_INFO xtradb_sys_zip_dict_fields_info[] =
601 {
602 	{ STRUCT_FLD(field_name, "id"),
603 	STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
604 	STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
605 	STRUCT_FLD(value, 0),
606 	STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
607 	STRUCT_FLD(old_name, ""),
608 	STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
609 
610 	{ STRUCT_FLD(field_name, "name"),
611 	STRUCT_FLD(field_length, ZIP_DICT_MAX_NAME_LENGTH),
612 	STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
613 	STRUCT_FLD(value, 0),
614 	STRUCT_FLD(field_flags, 0),
615 	STRUCT_FLD(old_name, ""),
616 	STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
617 
618 	{ STRUCT_FLD(field_name, "zip_dict"),
619 	STRUCT_FLD(field_length, ZIP_DICT_MAX_DATA_LENGTH),
620 	STRUCT_FLD(field_type, MYSQL_TYPE_BLOB),
621 	STRUCT_FLD(value, 0),
622 	STRUCT_FLD(field_flags, 0),
623 	STRUCT_FLD(old_name, ""),
624 	STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
625 
626 	END_OF_ST_FIELD_INFO
627 };
628 
629 /** Function to fill INFORMATION_SCHEMA.XTRADB_ZIP_DICT with information
630 collected by scanning SYS_ZIP_DICT table.
631 @return 0 on success */
632 static
633 int
xtradb_i_s_dict_fill_sys_zip_dict(THD * thd,ulint id,const char * name,const char * data,ulint data_len,TABLE * table_to_fill)634 xtradb_i_s_dict_fill_sys_zip_dict(
635 	THD*		thd,		/*!< in: thread */
636 	ulint		id,		/*!< in: dict ID */
637 	const char*	name,		/*!< in: dict name */
638 	const char*	data,		/*!< in: dict data */
639 	ulint		data_len,	/*!< in: dict data length */
640 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
641 {
642 	DBUG_ENTER("xtradb_i_s_dict_fill_sys_zip_dict");
643 
644 	Field**	fields = table_to_fill->field;
645 
646 	OK(field_store_ulint(fields[zip_dict_field_id], id));
647 	OK(field_store_string(fields[zip_dict_field_name], name));
648 	OK(field_store_blob(fields[zip_dict_field_zip_dict], data,
649 		data_len));
650 
651 	OK(schema_table_store_record(thd, table_to_fill));
652 
653 	DBUG_RETURN(0);
654 }
655 
656 /** Function to populate INFORMATION_SCHEMA.XTRADB_ZIP_DICT table.
657 Loop through each record in SYS_ZIP_DICT, and extract the column
658 information and fill the INFORMATION_SCHEMA.XTRADB_ZIP_DICT table.
659 @return 0 on success */
660 static
661 int
xtradb_i_s_sys_zip_dict_fill_table(THD * thd,TABLE_LIST * tables,Item *)662 xtradb_i_s_sys_zip_dict_fill_table(
663 	THD*		thd,	/*!< in: thread */
664 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
665 	Item*		)	/*!< in: condition (not used) */
666 {
667 	btr_pcur_t	pcur;
668 	const rec_t*	rec;
669 	mem_heap_t*	heap;
670 	mtr_t		mtr;
671 
672 	DBUG_ENTER("xtradb_i_s_sys_zip_dict_fill_table");
673 
674 	/* deny access to user without SUPER_ACL privilege */
675 	if (check_global_access(thd, SUPER_ACL)) {
676 		DBUG_RETURN(0);
677 	}
678 
679 	heap = mem_heap_create(1000);
680 	mutex_enter(&dict_sys->mutex);
681 	mtr_start(&mtr);
682 
683 	rec = dict_startscan_system(&pcur, &mtr, SYS_ZIP_DICT);
684 	page_size_t page_size = dict_table_page_size(
685 		pcur.btr_cur.index->table);
686 
687 	while (rec) {
688 		const char*	err_msg;
689 		ulint		id;
690 		const char*	name;
691 		const char*	data;
692 		ulint		data_len;
693 
694 		/* Extract necessary information from a SYS_ZIP_DICT row */
695 		err_msg = dict_process_sys_zip_dict(
696 			heap, page_size, rec, &id, &name, &data, &data_len);
697 
698 		mtr_commit(&mtr);
699 		mutex_exit(&dict_sys->mutex);
700 
701 		if (!err_msg) {
702 			xtradb_i_s_dict_fill_sys_zip_dict(
703 				thd, id, name, data, data_len,
704 				tables->table);
705 		} else {
706 			push_warning_printf(thd,
707 				Sql_condition::SL_WARNING,
708 				ER_CANT_FIND_SYSTEM_REC, "%s", err_msg);
709 		}
710 
711 		mem_heap_empty(heap);
712 
713 		/* Get the next record */
714 		mutex_enter(&dict_sys->mutex);
715 		mtr_start(&mtr);
716 		rec = dict_getnext_system(&pcur, &mtr);
717 	}
718 
719 	mtr_commit(&mtr);
720 	mutex_exit(&dict_sys->mutex);
721 	mem_heap_free(heap);
722 
723 	DBUG_RETURN(0);
724 }
725 
i_s_xtradb_zip_dict_init(void * p)726 static int i_s_xtradb_zip_dict_init(void* p)
727 {
728 	DBUG_ENTER("i_s_xtradb_zip_dict_init");
729 
730 	ST_SCHEMA_TABLE* schema = static_cast<ST_SCHEMA_TABLE*>(p);
731 
732 	schema->fields_info = xtradb_sys_zip_dict_fields_info;
733 	schema->fill_table = xtradb_i_s_sys_zip_dict_fill_table;
734 
735 	DBUG_RETURN(0);
736 }
737 
738 struct st_mysql_plugin	i_s_xtradb_zip_dict =
739 {
740 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
741 	STRUCT_FLD(info, &i_s_info),
742 	STRUCT_FLD(name, "XTRADB_ZIP_DICT"),
743 	STRUCT_FLD(author, PLUGIN_AUTHOR),
744 	STRUCT_FLD(descr, "InnoDB compression dictionaries information"),
745 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
746 	STRUCT_FLD(init, i_s_xtradb_zip_dict_init),
747 	STRUCT_FLD(deinit, i_s_common_deinit),
748 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
749 	STRUCT_FLD(status_vars, NULL),
750 	STRUCT_FLD(system_vars, NULL),
751 	STRUCT_FLD(__reserved1, NULL),
752 	STRUCT_FLD(flags, 0UL),
753 };
754 
755 enum zip_dict_cols_field_type
756 {
757 	zip_dict_cols_field_table_id,
758 	zip_dict_cols_field_column_pos,
759 	zip_dict_cols_field_dict_id
760 };
761 
762 static ST_FIELD_INFO xtradb_sys_zip_dict_cols_fields_info[] =
763 {
764 	{ STRUCT_FLD(field_name, "table_id"),
765 	STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
766 	STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
767 	STRUCT_FLD(value, 0),
768 	STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
769 	STRUCT_FLD(old_name, ""),
770 	STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
771 
772 	{ STRUCT_FLD(field_name, "column_pos"),
773 	STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
774 	STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
775 	STRUCT_FLD(value, 0),
776 	STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
777 	STRUCT_FLD(old_name, ""),
778 	STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
779 
780 	{ STRUCT_FLD(field_name, "dict_id"),
781 	STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
782 	STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
783 	STRUCT_FLD(value, 0),
784 	STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
785 	STRUCT_FLD(old_name, ""),
786 	STRUCT_FLD(open_method, SKIP_OPEN_TABLE) },
787 
788 	END_OF_ST_FIELD_INFO
789 };
790 
791 /** Function to fill INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS with information
792 collected by scanning SYS_ZIP_DICT_COLS table.
793 @return 0 on success */
794 static
795 int
xtradb_i_s_dict_fill_sys_zip_dict_cols(THD * thd,table_id_t table_id,ulint column_pos,ulint dict_id,TABLE * table_to_fill)796 xtradb_i_s_dict_fill_sys_zip_dict_cols(
797 	THD*		thd,		/*!< in: thread */
798 	table_id_t	table_id,	/*!< in: table ID */
799 	ulint		column_pos,	/*!< in: column position */
800 	ulint		dict_id,	/*!< in: dict ID */
801 	TABLE*		table_to_fill)	/*!< in/out: fill this table */
802 {
803 	DBUG_ENTER("xtradb_i_s_dict_fill_sys_zip_dict_cols");
804 
805 	Field**	fields = table_to_fill->field;
806 
807 	OK(field_store_ulint(fields[zip_dict_cols_field_table_id],
808 		table_id));
809 	OK(field_store_ulint(fields[zip_dict_cols_field_column_pos],
810 		column_pos));
811 	OK(field_store_ulint(fields[zip_dict_cols_field_dict_id],
812 		dict_id));
813 
814 	OK(schema_table_store_record(thd, table_to_fill));
815 
816 	DBUG_RETURN(0);
817 }
818 
819 /** Function to populate INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS table.
820 Loop through each record in SYS_ZIP_DICT_COLS, and extract the column
821 information and fill the INFORMATION_SCHEMA.XTRADB_ZIP_DICT_COLS table.
822 @return 0 on success */
823 static
824 int
xtradb_i_s_sys_zip_dict_cols_fill_table(THD * thd,TABLE_LIST * tables,Item *)825 xtradb_i_s_sys_zip_dict_cols_fill_table(
826 	THD*		thd,	/*!< in: thread */
827 	TABLE_LIST*	tables,	/*!< in/out: tables to fill */
828 	Item*		)	/*!< in: condition (not used) */
829 {
830 	btr_pcur_t	pcur;
831 	const rec_t*	rec;
832 	mem_heap_t*	heap;
833 	mtr_t		mtr;
834 
835 	DBUG_ENTER("xtradb_i_s_sys_zip_dict_cols_fill_table");
836 
837 	/* deny access to user without SUPER_ACL privilege */
838 	if (check_global_access(thd, SUPER_ACL)) {
839 		DBUG_RETURN(0);
840 	}
841 
842 	heap = mem_heap_create(1000);
843 	mutex_enter(&dict_sys->mutex);
844 	mtr_start(&mtr);
845 
846 	rec = dict_startscan_system(&pcur, &mtr, SYS_ZIP_DICT_COLS);
847 
848 	while (rec) {
849 		const char*	err_msg;
850 		table_id_t table_id;
851 		ulint column_pos;
852 		ulint dict_id;
853 
854 		/* Extract necessary information from a SYS_ZIP_DICT_COLS
855 		row */
856 		err_msg = dict_process_sys_zip_dict_cols(
857 			heap, rec, &table_id, &column_pos, &dict_id);
858 
859 		mtr_commit(&mtr);
860 		mutex_exit(&dict_sys->mutex);
861 
862 		if (!err_msg) {
863 			xtradb_i_s_dict_fill_sys_zip_dict_cols(
864 				thd, table_id, column_pos, dict_id,
865 				tables->table);
866 		} else {
867 			push_warning_printf(thd,
868 				Sql_condition::SL_WARNING,
869 				ER_CANT_FIND_SYSTEM_REC, "%s", err_msg);
870 		}
871 
872 		mem_heap_empty(heap);
873 
874 		/* Get the next record */
875 		mutex_enter(&dict_sys->mutex);
876 		mtr_start(&mtr);
877 		rec = dict_getnext_system(&pcur, &mtr);
878 	}
879 
880 	mtr_commit(&mtr);
881 	mutex_exit(&dict_sys->mutex);
882 	mem_heap_free(heap);
883 
884 	DBUG_RETURN(0);
885 }
886 
i_s_xtradb_zip_dict_cols_init(void * p)887 static int i_s_xtradb_zip_dict_cols_init(void* p)
888 {
889 	DBUG_ENTER("i_s_xtradb_zip_dict_cols_init");
890 
891 	ST_SCHEMA_TABLE* schema = static_cast<ST_SCHEMA_TABLE*>(p);
892 
893 	schema->fields_info = xtradb_sys_zip_dict_cols_fields_info;
894 	schema->fill_table = xtradb_i_s_sys_zip_dict_cols_fill_table;
895 
896 	DBUG_RETURN(0);
897 }
898 
899 struct st_mysql_plugin	i_s_xtradb_zip_dict_cols =
900 {
901 	STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
902 	STRUCT_FLD(info, &i_s_info),
903 	STRUCT_FLD(name, "XTRADB_ZIP_DICT_COLS"),
904 	STRUCT_FLD(author, PLUGIN_AUTHOR),
905 	STRUCT_FLD(descr, "InnoDB compressed columns information"),
906 	STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
907 	STRUCT_FLD(init, i_s_xtradb_zip_dict_cols_init),
908 	STRUCT_FLD(deinit, i_s_common_deinit),
909 	STRUCT_FLD(version, INNODB_VERSION_SHORT),
910 	STRUCT_FLD(status_vars, NULL),
911 	STRUCT_FLD(system_vars, NULL),
912 	STRUCT_FLD(__reserved1, NULL),
913 	STRUCT_FLD(flags, 0UL),
914 };
915