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