You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1578 lines
42 KiB

  1. /*****************************************************************************
  2. Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
  3. This program is free software; you can redistribute it and/or modify it under
  4. the terms of the GNU General Public License as published by the Free Software
  5. Foundation; version 2 of the License.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along with
  10. this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  11. Place, Suite 330, Boston, MA 02111-1307 USA
  12. *****************************************************************************/
  13. /**************************************************//**
  14. @file handler/i_s.cc
  15. InnoDB INFORMATION SCHEMA tables interface to MySQL.
  16. Created July 18, 2007 Vasil Dimov
  17. *******************************************************/
  18. #include <mysql_priv.h>
  19. #include <mysqld_error.h>
  20. #include <m_ctype.h>
  21. #include <hash.h>
  22. #include <myisampack.h>
  23. #include <mysys_err.h>
  24. #include <my_sys.h>
  25. #include "i_s.h"
  26. #include <mysql/plugin.h>
  27. extern "C" {
  28. #include "trx0i_s.h"
  29. #include "trx0trx.h" /* for TRX_QUE_STATE_STR_MAX_LEN */
  30. #include "buf0buddy.h" /* for i_s_cmpmem */
  31. #include "buf0buf.h" /* for buf_pool and PAGE_ZIP_MIN_SIZE */
  32. #include "ha_prototypes.h" /* for innobase_convert_name() */
  33. #include "srv0start.h" /* for srv_was_started */
  34. }
  35. static const char plugin_author[] = "Innobase Oy";
  36. #define OK(expr) \
  37. if ((expr) != 0) { \
  38. DBUG_RETURN(1); \
  39. }
  40. #define RETURN_IF_INNODB_NOT_STARTED(plugin_name) \
  41. do { \
  42. if (!srv_was_started) { \
  43. push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, \
  44. ER_CANT_FIND_SYSTEM_REC, \
  45. "InnoDB: SELECTing from " \
  46. "INFORMATION_SCHEMA.%s but " \
  47. "the InnoDB storage engine " \
  48. "is not installed", plugin_name); \
  49. DBUG_RETURN(0); \
  50. } \
  51. } while (0)
  52. #if !defined __STRICT_ANSI__ && defined __GNUC__ && (__GNUC__) > 2 && !defined __INTEL_COMPILER
  53. #define STRUCT_FLD(name, value) name: value
  54. #else
  55. #define STRUCT_FLD(name, value) value
  56. #endif
  57. /* Don't use a static const variable here, as some C++ compilers (notably
  58. HPUX aCC: HP ANSI C++ B3910B A.03.65) can't handle it. */
  59. #define END_OF_ST_FIELD_INFO \
  60. {STRUCT_FLD(field_name, NULL), \
  61. STRUCT_FLD(field_length, 0), \
  62. STRUCT_FLD(field_type, MYSQL_TYPE_NULL), \
  63. STRUCT_FLD(value, 0), \
  64. STRUCT_FLD(field_flags, 0), \
  65. STRUCT_FLD(old_name, ""), \
  66. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)}
  67. /*
  68. Use the following types mapping:
  69. C type ST_FIELD_INFO::field_type
  70. ---------------------------------
  71. long MYSQL_TYPE_LONGLONG
  72. (field_length=MY_INT64_NUM_DECIMAL_DIGITS)
  73. long unsigned MYSQL_TYPE_LONGLONG
  74. (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
  75. char* MYSQL_TYPE_STRING
  76. (field_length=n)
  77. float MYSQL_TYPE_FLOAT
  78. (field_length=0 is ignored)
  79. void* MYSQL_TYPE_LONGLONG
  80. (field_length=MY_INT64_NUM_DECIMAL_DIGITS, field_flags=MY_I_S_UNSIGNED)
  81. boolean (if else) MYSQL_TYPE_LONG
  82. (field_length=1)
  83. time_t MYSQL_TYPE_DATETIME
  84. (field_length=0 ignored)
  85. ---------------------------------
  86. */
  87. /* XXX these are defined in mysql_priv.h inside #ifdef MYSQL_SERVER */
  88. bool schema_table_store_record(THD *thd, TABLE *table);
  89. void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
  90. bool check_global_access(THD *thd, ulong want_access);
  91. /*******************************************************************//**
  92. Common function to fill any of the dynamic tables:
  93. INFORMATION_SCHEMA.innodb_trx
  94. INFORMATION_SCHEMA.innodb_locks
  95. INFORMATION_SCHEMA.innodb_lock_waits
  96. @return 0 on success */
  97. static
  98. int
  99. trx_i_s_common_fill_table(
  100. /*======================*/
  101. THD* thd, /*!< in: thread */
  102. TABLE_LIST* tables, /*!< in/out: tables to fill */
  103. COND* cond); /*!< in: condition (not used) */
  104. /*******************************************************************//**
  105. Unbind a dynamic INFORMATION_SCHEMA table.
  106. @return 0 on success */
  107. static
  108. int
  109. i_s_common_deinit(
  110. /*==============*/
  111. void* p); /*!< in/out: table schema object */
  112. /*******************************************************************//**
  113. Auxiliary function to store time_t value in MYSQL_TYPE_DATETIME
  114. field.
  115. @return 0 on success */
  116. static
  117. int
  118. field_store_time_t(
  119. /*===============*/
  120. Field* field, /*!< in/out: target field for storage */
  121. time_t time) /*!< in: value to store */
  122. {
  123. MYSQL_TIME my_time;
  124. struct tm tm_time;
  125. #if 0
  126. /* use this if you are sure that `variables' and `time_zone'
  127. are always initialized */
  128. thd->variables.time_zone->gmt_sec_to_TIME(
  129. &my_time, (my_time_t) time);
  130. #else
  131. localtime_r(&time, &tm_time);
  132. localtime_to_TIME(&my_time, &tm_time);
  133. my_time.time_type = MYSQL_TIMESTAMP_DATETIME;
  134. #endif
  135. return(field->store_time(&my_time, MYSQL_TIMESTAMP_DATETIME));
  136. }
  137. /*******************************************************************//**
  138. Auxiliary function to store char* value in MYSQL_TYPE_STRING field.
  139. @return 0 on success */
  140. static
  141. int
  142. field_store_string(
  143. /*===============*/
  144. Field* field, /*!< in/out: target field for storage */
  145. const char* str) /*!< in: NUL-terminated utf-8 string,
  146. or NULL */
  147. {
  148. int ret;
  149. if (str != NULL) {
  150. ret = field->store(str, strlen(str),
  151. system_charset_info);
  152. field->set_notnull();
  153. } else {
  154. ret = 0; /* success */
  155. field->set_null();
  156. }
  157. return(ret);
  158. }
  159. /*******************************************************************//**
  160. Auxiliary function to store ulint value in MYSQL_TYPE_LONGLONG field.
  161. If the value is ULINT_UNDEFINED then the field it set to NULL.
  162. @return 0 on success */
  163. static
  164. int
  165. field_store_ulint(
  166. /*==============*/
  167. Field* field, /*!< in/out: target field for storage */
  168. ulint n) /*!< in: value to store */
  169. {
  170. int ret;
  171. if (n != ULINT_UNDEFINED) {
  172. ret = field->store(n);
  173. field->set_notnull();
  174. } else {
  175. ret = 0; /* success */
  176. field->set_null();
  177. }
  178. return(ret);
  179. }
  180. /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_trx */
  181. static ST_FIELD_INFO innodb_trx_fields_info[] =
  182. {
  183. #define IDX_TRX_ID 0
  184. {STRUCT_FLD(field_name, "trx_id"),
  185. STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
  186. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  187. STRUCT_FLD(value, 0),
  188. STRUCT_FLD(field_flags, 0),
  189. STRUCT_FLD(old_name, ""),
  190. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  191. #define IDX_TRX_STATE 1
  192. {STRUCT_FLD(field_name, "trx_state"),
  193. STRUCT_FLD(field_length, TRX_QUE_STATE_STR_MAX_LEN + 1),
  194. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  195. STRUCT_FLD(value, 0),
  196. STRUCT_FLD(field_flags, 0),
  197. STRUCT_FLD(old_name, ""),
  198. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  199. #define IDX_TRX_STARTED 2
  200. {STRUCT_FLD(field_name, "trx_started"),
  201. STRUCT_FLD(field_length, 0),
  202. STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
  203. STRUCT_FLD(value, 0),
  204. STRUCT_FLD(field_flags, 0),
  205. STRUCT_FLD(old_name, ""),
  206. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  207. #define IDX_TRX_REQUESTED_LOCK_ID 3
  208. {STRUCT_FLD(field_name, "trx_requested_lock_id"),
  209. STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
  210. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  211. STRUCT_FLD(value, 0),
  212. STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
  213. STRUCT_FLD(old_name, ""),
  214. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  215. #define IDX_TRX_WAIT_STARTED 4
  216. {STRUCT_FLD(field_name, "trx_wait_started"),
  217. STRUCT_FLD(field_length, 0),
  218. STRUCT_FLD(field_type, MYSQL_TYPE_DATETIME),
  219. STRUCT_FLD(value, 0),
  220. STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
  221. STRUCT_FLD(old_name, ""),
  222. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  223. #define IDX_TRX_WEIGHT 5
  224. {STRUCT_FLD(field_name, "trx_weight"),
  225. STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
  226. STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
  227. STRUCT_FLD(value, 0),
  228. STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
  229. STRUCT_FLD(old_name, ""),
  230. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  231. #define IDX_TRX_MYSQL_THREAD_ID 6
  232. {STRUCT_FLD(field_name, "trx_mysql_thread_id"),
  233. STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
  234. STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
  235. STRUCT_FLD(value, 0),
  236. STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
  237. STRUCT_FLD(old_name, ""),
  238. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  239. #define IDX_TRX_QUERY 7
  240. {STRUCT_FLD(field_name, "trx_query"),
  241. STRUCT_FLD(field_length, TRX_I_S_TRX_QUERY_MAX_LEN),
  242. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  243. STRUCT_FLD(value, 0),
  244. STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
  245. STRUCT_FLD(old_name, ""),
  246. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  247. END_OF_ST_FIELD_INFO
  248. };
  249. /*******************************************************************//**
  250. Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_trx
  251. table with it.
  252. @return 0 on success */
  253. static
  254. int
  255. fill_innodb_trx_from_cache(
  256. /*=======================*/
  257. trx_i_s_cache_t* cache, /*!< in: cache to read from */
  258. THD* thd, /*!< in: used to call
  259. schema_table_store_record() */
  260. TABLE* table) /*!< in/out: fill this table */
  261. {
  262. Field** fields;
  263. ulint rows_num;
  264. char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
  265. ulint i;
  266. DBUG_ENTER("fill_innodb_trx_from_cache");
  267. fields = table->field;
  268. rows_num = trx_i_s_cache_get_rows_used(cache,
  269. I_S_INNODB_TRX);
  270. for (i = 0; i < rows_num; i++) {
  271. i_s_trx_row_t* row;
  272. char trx_id[TRX_ID_MAX_LEN + 1];
  273. row = (i_s_trx_row_t*)
  274. trx_i_s_cache_get_nth_row(
  275. cache, I_S_INNODB_TRX, i);
  276. /* trx_id */
  277. ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id);
  278. OK(field_store_string(fields[IDX_TRX_ID], trx_id));
  279. /* trx_state */
  280. OK(field_store_string(fields[IDX_TRX_STATE],
  281. row->trx_state));
  282. /* trx_started */
  283. OK(field_store_time_t(fields[IDX_TRX_STARTED],
  284. (time_t) row->trx_started));
  285. /* trx_requested_lock_id */
  286. /* trx_wait_started */
  287. if (row->trx_wait_started != 0) {
  288. OK(field_store_string(
  289. fields[IDX_TRX_REQUESTED_LOCK_ID],
  290. trx_i_s_create_lock_id(
  291. row->requested_lock_row,
  292. lock_id, sizeof(lock_id))));
  293. /* field_store_string() sets it no notnull */
  294. OK(field_store_time_t(
  295. fields[IDX_TRX_WAIT_STARTED],
  296. (time_t) row->trx_wait_started));
  297. fields[IDX_TRX_WAIT_STARTED]->set_notnull();
  298. } else {
  299. fields[IDX_TRX_REQUESTED_LOCK_ID]->set_null();
  300. fields[IDX_TRX_WAIT_STARTED]->set_null();
  301. }
  302. /* trx_weight */
  303. OK(fields[IDX_TRX_WEIGHT]->store((longlong) row->trx_weight,
  304. true));
  305. /* trx_mysql_thread_id */
  306. OK(fields[IDX_TRX_MYSQL_THREAD_ID]->store(
  307. row->trx_mysql_thread_id));
  308. /* trx_query */
  309. OK(field_store_string(fields[IDX_TRX_QUERY],
  310. row->trx_query));
  311. OK(schema_table_store_record(thd, table));
  312. }
  313. DBUG_RETURN(0);
  314. }
  315. /*******************************************************************//**
  316. Bind the dynamic table INFORMATION_SCHEMA.innodb_trx
  317. @return 0 on success */
  318. static
  319. int
  320. innodb_trx_init(
  321. /*============*/
  322. void* p) /*!< in/out: table schema object */
  323. {
  324. ST_SCHEMA_TABLE* schema;
  325. DBUG_ENTER("innodb_trx_init");
  326. schema = (ST_SCHEMA_TABLE*) p;
  327. schema->fields_info = innodb_trx_fields_info;
  328. schema->fill_table = trx_i_s_common_fill_table;
  329. DBUG_RETURN(0);
  330. }
  331. static struct st_mysql_information_schema i_s_info =
  332. {
  333. MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
  334. };
  335. UNIV_INTERN struct st_mysql_plugin i_s_innodb_trx =
  336. {
  337. /* the plugin type (a MYSQL_XXX_PLUGIN value) */
  338. /* int */
  339. STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
  340. /* pointer to type-specific plugin descriptor */
  341. /* void* */
  342. STRUCT_FLD(info, &i_s_info),
  343. /* plugin name */
  344. /* const char* */
  345. STRUCT_FLD(name, "INNODB_TRX"),
  346. /* plugin author (for SHOW PLUGINS) */
  347. /* const char* */
  348. STRUCT_FLD(author, plugin_author),
  349. /* general descriptive text (for SHOW PLUGINS) */
  350. /* const char* */
  351. STRUCT_FLD(descr, "InnoDB transactions"),
  352. /* the plugin license (PLUGIN_LICENSE_XXX) */
  353. /* int */
  354. STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
  355. /* the function to invoke when plugin is loaded */
  356. /* int (*)(void*); */
  357. STRUCT_FLD(init, innodb_trx_init),
  358. /* the function to invoke when plugin is unloaded */
  359. /* int (*)(void*); */
  360. STRUCT_FLD(deinit, i_s_common_deinit),
  361. /* plugin version (for SHOW PLUGINS) */
  362. /* unsigned int */
  363. STRUCT_FLD(version, INNODB_VERSION_SHORT),
  364. /* struct st_mysql_show_var* */
  365. STRUCT_FLD(status_vars, NULL),
  366. /* struct st_mysql_sys_var** */
  367. STRUCT_FLD(system_vars, NULL),
  368. /* reserved for dependency checking */
  369. /* void* */
  370. STRUCT_FLD(__reserved1, NULL)
  371. };
  372. /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_locks */
  373. static ST_FIELD_INFO innodb_locks_fields_info[] =
  374. {
  375. #define IDX_LOCK_ID 0
  376. {STRUCT_FLD(field_name, "lock_id"),
  377. STRUCT_FLD(field_length, TRX_I_S_LOCK_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. #define IDX_LOCK_TRX_ID 1
  384. {STRUCT_FLD(field_name, "lock_trx_id"),
  385. STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
  386. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  387. STRUCT_FLD(value, 0),
  388. STRUCT_FLD(field_flags, 0),
  389. STRUCT_FLD(old_name, ""),
  390. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  391. #define IDX_LOCK_MODE 2
  392. {STRUCT_FLD(field_name, "lock_mode"),
  393. /* S[,GAP] X[,GAP] IS[,GAP] IX[,GAP] AUTO_INC UNKNOWN */
  394. STRUCT_FLD(field_length, 32),
  395. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  396. STRUCT_FLD(value, 0),
  397. STRUCT_FLD(field_flags, 0),
  398. STRUCT_FLD(old_name, ""),
  399. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  400. #define IDX_LOCK_TYPE 3
  401. {STRUCT_FLD(field_name, "lock_type"),
  402. STRUCT_FLD(field_length, 32 /* RECORD|TABLE|UNKNOWN */),
  403. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  404. STRUCT_FLD(value, 0),
  405. STRUCT_FLD(field_flags, 0),
  406. STRUCT_FLD(old_name, ""),
  407. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  408. #define IDX_LOCK_TABLE 4
  409. {STRUCT_FLD(field_name, "lock_table"),
  410. STRUCT_FLD(field_length, 1024),
  411. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  412. STRUCT_FLD(value, 0),
  413. STRUCT_FLD(field_flags, 0),
  414. STRUCT_FLD(old_name, ""),
  415. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  416. #define IDX_LOCK_INDEX 5
  417. {STRUCT_FLD(field_name, "lock_index"),
  418. STRUCT_FLD(field_length, 1024),
  419. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  420. STRUCT_FLD(value, 0),
  421. STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
  422. STRUCT_FLD(old_name, ""),
  423. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  424. #define IDX_LOCK_SPACE 6
  425. {STRUCT_FLD(field_name, "lock_space"),
  426. STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
  427. STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
  428. STRUCT_FLD(value, 0),
  429. STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
  430. STRUCT_FLD(old_name, ""),
  431. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  432. #define IDX_LOCK_PAGE 7
  433. {STRUCT_FLD(field_name, "lock_page"),
  434. STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
  435. STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
  436. STRUCT_FLD(value, 0),
  437. STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
  438. STRUCT_FLD(old_name, ""),
  439. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  440. #define IDX_LOCK_REC 8
  441. {STRUCT_FLD(field_name, "lock_rec"),
  442. STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
  443. STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
  444. STRUCT_FLD(value, 0),
  445. STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
  446. STRUCT_FLD(old_name, ""),
  447. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  448. #define IDX_LOCK_DATA 9
  449. {STRUCT_FLD(field_name, "lock_data"),
  450. STRUCT_FLD(field_length, TRX_I_S_LOCK_DATA_MAX_LEN),
  451. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  452. STRUCT_FLD(value, 0),
  453. STRUCT_FLD(field_flags, MY_I_S_MAYBE_NULL),
  454. STRUCT_FLD(old_name, ""),
  455. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  456. END_OF_ST_FIELD_INFO
  457. };
  458. /*******************************************************************//**
  459. Read data from cache buffer and fill the INFORMATION_SCHEMA.innodb_locks
  460. table with it.
  461. @return 0 on success */
  462. static
  463. int
  464. fill_innodb_locks_from_cache(
  465. /*=========================*/
  466. trx_i_s_cache_t* cache, /*!< in: cache to read from */
  467. THD* thd, /*!< in: MySQL client connection */
  468. TABLE* table) /*!< in/out: fill this table */
  469. {
  470. Field** fields;
  471. ulint rows_num;
  472. char lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
  473. ulint i;
  474. DBUG_ENTER("fill_innodb_locks_from_cache");
  475. fields = table->field;
  476. rows_num = trx_i_s_cache_get_rows_used(cache,
  477. I_S_INNODB_LOCKS);
  478. for (i = 0; i < rows_num; i++) {
  479. i_s_locks_row_t* row;
  480. /* note that the decoded database or table name is
  481. never expected to be longer than NAME_LEN;
  482. NAME_LEN for database name
  483. 2 for surrounding quotes around database name
  484. NAME_LEN for table name
  485. 2 for surrounding quotes around table name
  486. 1 for the separating dot (.)
  487. 9 for the #mysql50# prefix */
  488. char buf[2 * NAME_LEN + 14];
  489. const char* bufend;
  490. char lock_trx_id[TRX_ID_MAX_LEN + 1];
  491. row = (i_s_locks_row_t*)
  492. trx_i_s_cache_get_nth_row(
  493. cache, I_S_INNODB_LOCKS, i);
  494. /* lock_id */
  495. trx_i_s_create_lock_id(row, lock_id, sizeof(lock_id));
  496. OK(field_store_string(fields[IDX_LOCK_ID],
  497. lock_id));
  498. /* lock_trx_id */
  499. ut_snprintf(lock_trx_id, sizeof(lock_trx_id),
  500. TRX_ID_FMT, row->lock_trx_id);
  501. OK(field_store_string(fields[IDX_LOCK_TRX_ID], lock_trx_id));
  502. /* lock_mode */
  503. OK(field_store_string(fields[IDX_LOCK_MODE],
  504. row->lock_mode));
  505. /* lock_type */
  506. OK(field_store_string(fields[IDX_LOCK_TYPE],
  507. row->lock_type));
  508. /* lock_table */
  509. bufend = innobase_convert_name(buf, sizeof(buf),
  510. row->lock_table,
  511. strlen(row->lock_table),
  512. thd, TRUE);
  513. OK(fields[IDX_LOCK_TABLE]->store(buf, bufend - buf,
  514. system_charset_info));
  515. /* lock_index */
  516. if (row->lock_index != NULL) {
  517. bufend = innobase_convert_name(buf, sizeof(buf),
  518. row->lock_index,
  519. strlen(row->lock_index),
  520. thd, FALSE);
  521. OK(fields[IDX_LOCK_INDEX]->store(buf, bufend - buf,
  522. system_charset_info));
  523. fields[IDX_LOCK_INDEX]->set_notnull();
  524. } else {
  525. fields[IDX_LOCK_INDEX]->set_null();
  526. }
  527. /* lock_space */
  528. OK(field_store_ulint(fields[IDX_LOCK_SPACE],
  529. row->lock_space));
  530. /* lock_page */
  531. OK(field_store_ulint(fields[IDX_LOCK_PAGE],
  532. row->lock_page));
  533. /* lock_rec */
  534. OK(field_store_ulint(fields[IDX_LOCK_REC],
  535. row->lock_rec));
  536. /* lock_data */
  537. OK(field_store_string(fields[IDX_LOCK_DATA],
  538. row->lock_data));
  539. OK(schema_table_store_record(thd, table));
  540. }
  541. DBUG_RETURN(0);
  542. }
  543. /*******************************************************************//**
  544. Bind the dynamic table INFORMATION_SCHEMA.innodb_locks
  545. @return 0 on success */
  546. static
  547. int
  548. innodb_locks_init(
  549. /*==============*/
  550. void* p) /*!< in/out: table schema object */
  551. {
  552. ST_SCHEMA_TABLE* schema;
  553. DBUG_ENTER("innodb_locks_init");
  554. schema = (ST_SCHEMA_TABLE*) p;
  555. schema->fields_info = innodb_locks_fields_info;
  556. schema->fill_table = trx_i_s_common_fill_table;
  557. DBUG_RETURN(0);
  558. }
  559. UNIV_INTERN struct st_mysql_plugin i_s_innodb_locks =
  560. {
  561. /* the plugin type (a MYSQL_XXX_PLUGIN value) */
  562. /* int */
  563. STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
  564. /* pointer to type-specific plugin descriptor */
  565. /* void* */
  566. STRUCT_FLD(info, &i_s_info),
  567. /* plugin name */
  568. /* const char* */
  569. STRUCT_FLD(name, "INNODB_LOCKS"),
  570. /* plugin author (for SHOW PLUGINS) */
  571. /* const char* */
  572. STRUCT_FLD(author, plugin_author),
  573. /* general descriptive text (for SHOW PLUGINS) */
  574. /* const char* */
  575. STRUCT_FLD(descr, "InnoDB conflicting locks"),
  576. /* the plugin license (PLUGIN_LICENSE_XXX) */
  577. /* int */
  578. STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
  579. /* the function to invoke when plugin is loaded */
  580. /* int (*)(void*); */
  581. STRUCT_FLD(init, innodb_locks_init),
  582. /* the function to invoke when plugin is unloaded */
  583. /* int (*)(void*); */
  584. STRUCT_FLD(deinit, i_s_common_deinit),
  585. /* plugin version (for SHOW PLUGINS) */
  586. /* unsigned int */
  587. STRUCT_FLD(version, INNODB_VERSION_SHORT),
  588. /* struct st_mysql_show_var* */
  589. STRUCT_FLD(status_vars, NULL),
  590. /* struct st_mysql_sys_var** */
  591. STRUCT_FLD(system_vars, NULL),
  592. /* reserved for dependency checking */
  593. /* void* */
  594. STRUCT_FLD(__reserved1, NULL)
  595. };
  596. /* Fields of the dynamic table INFORMATION_SCHEMA.innodb_lock_waits */
  597. static ST_FIELD_INFO innodb_lock_waits_fields_info[] =
  598. {
  599. #define IDX_REQUESTING_TRX_ID 0
  600. {STRUCT_FLD(field_name, "requesting_trx_id"),
  601. STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
  602. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  603. STRUCT_FLD(value, 0),
  604. STRUCT_FLD(field_flags, 0),
  605. STRUCT_FLD(old_name, ""),
  606. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  607. #define IDX_REQUESTED_LOCK_ID 1
  608. {STRUCT_FLD(field_name, "requested_lock_id"),
  609. STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
  610. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  611. STRUCT_FLD(value, 0),
  612. STRUCT_FLD(field_flags, 0),
  613. STRUCT_FLD(old_name, ""),
  614. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  615. #define IDX_BLOCKING_TRX_ID 2
  616. {STRUCT_FLD(field_name, "blocking_trx_id"),
  617. STRUCT_FLD(field_length, TRX_ID_MAX_LEN + 1),
  618. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  619. STRUCT_FLD(value, 0),
  620. STRUCT_FLD(field_flags, 0),
  621. STRUCT_FLD(old_name, ""),
  622. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  623. #define IDX_BLOCKING_LOCK_ID 3
  624. {STRUCT_FLD(field_name, "blocking_lock_id"),
  625. STRUCT_FLD(field_length, TRX_I_S_LOCK_ID_MAX_LEN + 1),
  626. STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
  627. STRUCT_FLD(value, 0),
  628. STRUCT_FLD(field_flags, 0),
  629. STRUCT_FLD(old_name, ""),
  630. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  631. END_OF_ST_FIELD_INFO
  632. };
  633. /*******************************************************************//**
  634. Read data from cache buffer and fill the
  635. INFORMATION_SCHEMA.innodb_lock_waits table with it.
  636. @return 0 on success */
  637. static
  638. int
  639. fill_innodb_lock_waits_from_cache(
  640. /*==============================*/
  641. trx_i_s_cache_t* cache, /*!< in: cache to read from */
  642. THD* thd, /*!< in: used to call
  643. schema_table_store_record() */
  644. TABLE* table) /*!< in/out: fill this table */
  645. {
  646. Field** fields;
  647. ulint rows_num;
  648. char requested_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
  649. char blocking_lock_id[TRX_I_S_LOCK_ID_MAX_LEN + 1];
  650. ulint i;
  651. DBUG_ENTER("fill_innodb_lock_waits_from_cache");
  652. fields = table->field;
  653. rows_num = trx_i_s_cache_get_rows_used(cache,
  654. I_S_INNODB_LOCK_WAITS);
  655. for (i = 0; i < rows_num; i++) {
  656. i_s_lock_waits_row_t* row;
  657. char requesting_trx_id[TRX_ID_MAX_LEN + 1];
  658. char blocking_trx_id[TRX_ID_MAX_LEN + 1];
  659. row = (i_s_lock_waits_row_t*)
  660. trx_i_s_cache_get_nth_row(
  661. cache, I_S_INNODB_LOCK_WAITS, i);
  662. /* requesting_trx_id */
  663. ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id),
  664. TRX_ID_FMT, row->requested_lock_row->lock_trx_id);
  665. OK(field_store_string(fields[IDX_REQUESTING_TRX_ID],
  666. requesting_trx_id));
  667. /* requested_lock_id */
  668. OK(field_store_string(
  669. fields[IDX_REQUESTED_LOCK_ID],
  670. trx_i_s_create_lock_id(
  671. row->requested_lock_row,
  672. requested_lock_id,
  673. sizeof(requested_lock_id))));
  674. /* blocking_trx_id */
  675. ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id),
  676. TRX_ID_FMT, row->blocking_lock_row->lock_trx_id);
  677. OK(field_store_string(fields[IDX_BLOCKING_TRX_ID],
  678. blocking_trx_id));
  679. /* blocking_lock_id */
  680. OK(field_store_string(
  681. fields[IDX_BLOCKING_LOCK_ID],
  682. trx_i_s_create_lock_id(
  683. row->blocking_lock_row,
  684. blocking_lock_id,
  685. sizeof(blocking_lock_id))));
  686. OK(schema_table_store_record(thd, table));
  687. }
  688. DBUG_RETURN(0);
  689. }
  690. /*******************************************************************//**
  691. Bind the dynamic table INFORMATION_SCHEMA.innodb_lock_waits
  692. @return 0 on success */
  693. static
  694. int
  695. innodb_lock_waits_init(
  696. /*===================*/
  697. void* p) /*!< in/out: table schema object */
  698. {
  699. ST_SCHEMA_TABLE* schema;
  700. DBUG_ENTER("innodb_lock_waits_init");
  701. schema = (ST_SCHEMA_TABLE*) p;
  702. schema->fields_info = innodb_lock_waits_fields_info;
  703. schema->fill_table = trx_i_s_common_fill_table;
  704. DBUG_RETURN(0);
  705. }
  706. UNIV_INTERN struct st_mysql_plugin i_s_innodb_lock_waits =
  707. {
  708. /* the plugin type (a MYSQL_XXX_PLUGIN value) */
  709. /* int */
  710. STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
  711. /* pointer to type-specific plugin descriptor */
  712. /* void* */
  713. STRUCT_FLD(info, &i_s_info),
  714. /* plugin name */
  715. /* const char* */
  716. STRUCT_FLD(name, "INNODB_LOCK_WAITS"),
  717. /* plugin author (for SHOW PLUGINS) */
  718. /* const char* */
  719. STRUCT_FLD(author, "Innobase Oy"),
  720. /* general descriptive text (for SHOW PLUGINS) */
  721. /* const char* */
  722. STRUCT_FLD(descr, "InnoDB which lock is blocking which"),
  723. /* the plugin license (PLUGIN_LICENSE_XXX) */
  724. /* int */
  725. STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
  726. /* the function to invoke when plugin is loaded */
  727. /* int (*)(void*); */
  728. STRUCT_FLD(init, innodb_lock_waits_init),
  729. /* the function to invoke when plugin is unloaded */
  730. /* int (*)(void*); */
  731. STRUCT_FLD(deinit, i_s_common_deinit),
  732. /* plugin version (for SHOW PLUGINS) */
  733. /* unsigned int */
  734. STRUCT_FLD(version, INNODB_VERSION_SHORT),
  735. /* struct st_mysql_show_var* */
  736. STRUCT_FLD(status_vars, NULL),
  737. /* struct st_mysql_sys_var** */
  738. STRUCT_FLD(system_vars, NULL),
  739. /* reserved for dependency checking */
  740. /* void* */
  741. STRUCT_FLD(__reserved1, NULL)
  742. };
  743. /*******************************************************************//**
  744. Common function to fill any of the dynamic tables:
  745. INFORMATION_SCHEMA.innodb_trx
  746. INFORMATION_SCHEMA.innodb_locks
  747. INFORMATION_SCHEMA.innodb_lock_waits
  748. @return 0 on success */
  749. static
  750. int
  751. trx_i_s_common_fill_table(
  752. /*======================*/
  753. THD* thd, /*!< in: thread */
  754. TABLE_LIST* tables, /*!< in/out: tables to fill */
  755. COND* cond) /*!< in: condition (not used) */
  756. {
  757. const char* table_name;
  758. int ret;
  759. trx_i_s_cache_t* cache;
  760. DBUG_ENTER("trx_i_s_common_fill_table");
  761. /* deny access to non-superusers */
  762. if (check_global_access(thd, PROCESS_ACL)) {
  763. DBUG_RETURN(0);
  764. }
  765. /* minimize the number of places where global variables are
  766. referenced */
  767. cache = trx_i_s_cache;
  768. /* which table we have to fill? */
  769. table_name = tables->schema_table_name;
  770. /* or table_name = tables->schema_table->table_name; */
  771. RETURN_IF_INNODB_NOT_STARTED(table_name);
  772. /* update the cache */
  773. trx_i_s_cache_start_write(cache);
  774. trx_i_s_possibly_fetch_data_into_cache(cache);
  775. trx_i_s_cache_end_write(cache);
  776. if (trx_i_s_cache_is_truncated(cache)) {
  777. /* XXX show warning to user if possible */
  778. fprintf(stderr, "Warning: data in %s truncated due to "
  779. "memory limit of %d bytes\n", table_name,
  780. TRX_I_S_MEM_LIMIT);
  781. }
  782. ret = 0;
  783. trx_i_s_cache_start_read(cache);
  784. if (innobase_strcasecmp(table_name, "innodb_trx") == 0) {
  785. if (fill_innodb_trx_from_cache(
  786. cache, thd, tables->table) != 0) {
  787. ret = 1;
  788. }
  789. } else if (innobase_strcasecmp(table_name, "innodb_locks") == 0) {
  790. if (fill_innodb_locks_from_cache(
  791. cache, thd, tables->table) != 0) {
  792. ret = 1;
  793. }
  794. } else if (innobase_strcasecmp(table_name, "innodb_lock_waits") == 0) {
  795. if (fill_innodb_lock_waits_from_cache(
  796. cache, thd, tables->table) != 0) {
  797. ret = 1;
  798. }
  799. } else {
  800. /* huh! what happened!? */
  801. fprintf(stderr,
  802. "InnoDB: trx_i_s_common_fill_table() was "
  803. "called to fill unknown table: %s.\n"
  804. "This function only knows how to fill "
  805. "innodb_trx, innodb_locks and "
  806. "innodb_lock_waits tables.\n", table_name);
  807. ret = 1;
  808. }
  809. trx_i_s_cache_end_read(cache);
  810. #if 0
  811. DBUG_RETURN(ret);
  812. #else
  813. /* if this function returns something else than 0 then a
  814. deadlock occurs between the mysqld server and mysql client,
  815. see http://bugs.mysql.com/29900 ; when that bug is resolved
  816. we can enable the DBUG_RETURN(ret) above */
  817. DBUG_RETURN(0);
  818. #endif
  819. }
  820. /* Fields of the dynamic table information_schema.innodb_cmp. */
  821. static ST_FIELD_INFO i_s_cmp_fields_info[] =
  822. {
  823. {STRUCT_FLD(field_name, "page_size"),
  824. STRUCT_FLD(field_length, 5),
  825. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  826. STRUCT_FLD(value, 0),
  827. STRUCT_FLD(field_flags, 0),
  828. STRUCT_FLD(old_name, "Compressed Page Size"),
  829. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  830. {STRUCT_FLD(field_name, "compress_ops"),
  831. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  832. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  833. STRUCT_FLD(value, 0),
  834. STRUCT_FLD(field_flags, 0),
  835. STRUCT_FLD(old_name, "Total Number of Compressions"),
  836. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  837. {STRUCT_FLD(field_name, "compress_ops_ok"),
  838. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  839. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  840. STRUCT_FLD(value, 0),
  841. STRUCT_FLD(field_flags, 0),
  842. STRUCT_FLD(old_name, "Total Number of"
  843. " Successful Compressions"),
  844. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  845. {STRUCT_FLD(field_name, "compress_time"),
  846. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  847. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  848. STRUCT_FLD(value, 0),
  849. STRUCT_FLD(field_flags, 0),
  850. STRUCT_FLD(old_name, "Total Duration of Compressions,"
  851. " in Seconds"),
  852. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  853. {STRUCT_FLD(field_name, "uncompress_ops"),
  854. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  855. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  856. STRUCT_FLD(value, 0),
  857. STRUCT_FLD(field_flags, 0),
  858. STRUCT_FLD(old_name, "Total Number of Decompressions"),
  859. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  860. {STRUCT_FLD(field_name, "uncompress_time"),
  861. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  862. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  863. STRUCT_FLD(value, 0),
  864. STRUCT_FLD(field_flags, 0),
  865. STRUCT_FLD(old_name, "Total Duration of Decompressions,"
  866. " in Seconds"),
  867. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  868. END_OF_ST_FIELD_INFO
  869. };
  870. /*******************************************************************//**
  871. Fill the dynamic table information_schema.innodb_cmp or
  872. innodb_cmp_reset.
  873. @return 0 on success, 1 on failure */
  874. static
  875. int
  876. i_s_cmp_fill_low(
  877. /*=============*/
  878. THD* thd, /*!< in: thread */
  879. TABLE_LIST* tables, /*!< in/out: tables to fill */
  880. COND* cond, /*!< in: condition (ignored) */
  881. ibool reset) /*!< in: TRUE=reset cumulated counts */
  882. {
  883. TABLE* table = (TABLE *) tables->table;
  884. int status = 0;
  885. DBUG_ENTER("i_s_cmp_fill_low");
  886. /* deny access to non-superusers */
  887. if (check_global_access(thd, PROCESS_ACL)) {
  888. DBUG_RETURN(0);
  889. }
  890. RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
  891. for (uint i = 0; i < PAGE_ZIP_NUM_SSIZE - 1; i++) {
  892. page_zip_stat_t* zip_stat = &page_zip_stat[i];
  893. table->field[0]->store(PAGE_ZIP_MIN_SIZE << i);
  894. /* The cumulated counts are not protected by any
  895. mutex. Thus, some operation in page0zip.c could
  896. increment a counter between the time we read it and
  897. clear it. We could introduce mutex protection, but it
  898. could cause a measureable performance hit in
  899. page0zip.c. */
  900. table->field[1]->store(zip_stat->compressed);
  901. table->field[2]->store(zip_stat->compressed_ok);
  902. table->field[3]->store(
  903. (ulong) (zip_stat->compressed_usec / 1000000));
  904. table->field[4]->store(zip_stat->decompressed);
  905. table->field[5]->store(
  906. (ulong) (zip_stat->decompressed_usec / 1000000));
  907. if (reset) {
  908. memset(zip_stat, 0, sizeof *zip_stat);
  909. }
  910. if (schema_table_store_record(thd, table)) {
  911. status = 1;
  912. break;
  913. }
  914. }
  915. DBUG_RETURN(status);
  916. }
  917. /*******************************************************************//**
  918. Fill the dynamic table information_schema.innodb_cmp.
  919. @return 0 on success, 1 on failure */
  920. static
  921. int
  922. i_s_cmp_fill(
  923. /*=========*/
  924. THD* thd, /*!< in: thread */
  925. TABLE_LIST* tables, /*!< in/out: tables to fill */
  926. COND* cond) /*!< in: condition (ignored) */
  927. {
  928. return(i_s_cmp_fill_low(thd, tables, cond, FALSE));
  929. }
  930. /*******************************************************************//**
  931. Fill the dynamic table information_schema.innodb_cmp_reset.
  932. @return 0 on success, 1 on failure */
  933. static
  934. int
  935. i_s_cmp_reset_fill(
  936. /*===============*/
  937. THD* thd, /*!< in: thread */
  938. TABLE_LIST* tables, /*!< in/out: tables to fill */
  939. COND* cond) /*!< in: condition (ignored) */
  940. {
  941. return(i_s_cmp_fill_low(thd, tables, cond, TRUE));
  942. }
  943. /*******************************************************************//**
  944. Bind the dynamic table information_schema.innodb_cmp.
  945. @return 0 on success */
  946. static
  947. int
  948. i_s_cmp_init(
  949. /*=========*/
  950. void* p) /*!< in/out: table schema object */
  951. {
  952. DBUG_ENTER("i_s_cmp_init");
  953. ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
  954. schema->fields_info = i_s_cmp_fields_info;
  955. schema->fill_table = i_s_cmp_fill;
  956. DBUG_RETURN(0);
  957. }
  958. /*******************************************************************//**
  959. Bind the dynamic table information_schema.innodb_cmp_reset.
  960. @return 0 on success */
  961. static
  962. int
  963. i_s_cmp_reset_init(
  964. /*===============*/
  965. void* p) /*!< in/out: table schema object */
  966. {
  967. DBUG_ENTER("i_s_cmp_reset_init");
  968. ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
  969. schema->fields_info = i_s_cmp_fields_info;
  970. schema->fill_table = i_s_cmp_reset_fill;
  971. DBUG_RETURN(0);
  972. }
  973. UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp =
  974. {
  975. /* the plugin type (a MYSQL_XXX_PLUGIN value) */
  976. /* int */
  977. STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
  978. /* pointer to type-specific plugin descriptor */
  979. /* void* */
  980. STRUCT_FLD(info, &i_s_info),
  981. /* plugin name */
  982. /* const char* */
  983. STRUCT_FLD(name, "INNODB_CMP"),
  984. /* plugin author (for SHOW PLUGINS) */
  985. /* const char* */
  986. STRUCT_FLD(author, plugin_author),
  987. /* general descriptive text (for SHOW PLUGINS) */
  988. /* const char* */
  989. STRUCT_FLD(descr, "Statistics for the InnoDB compression"),
  990. /* the plugin license (PLUGIN_LICENSE_XXX) */
  991. /* int */
  992. STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
  993. /* the function to invoke when plugin is loaded */
  994. /* int (*)(void*); */
  995. STRUCT_FLD(init, i_s_cmp_init),
  996. /* the function to invoke when plugin is unloaded */
  997. /* int (*)(void*); */
  998. STRUCT_FLD(deinit, i_s_common_deinit),
  999. /* plugin version (for SHOW PLUGINS) */
  1000. /* unsigned int */
  1001. STRUCT_FLD(version, INNODB_VERSION_SHORT),
  1002. /* struct st_mysql_show_var* */
  1003. STRUCT_FLD(status_vars, NULL),
  1004. /* struct st_mysql_sys_var** */
  1005. STRUCT_FLD(system_vars, NULL),
  1006. /* reserved for dependency checking */
  1007. /* void* */
  1008. STRUCT_FLD(__reserved1, NULL)
  1009. };
  1010. UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmp_reset =
  1011. {
  1012. /* the plugin type (a MYSQL_XXX_PLUGIN value) */
  1013. /* int */
  1014. STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
  1015. /* pointer to type-specific plugin descriptor */
  1016. /* void* */
  1017. STRUCT_FLD(info, &i_s_info),
  1018. /* plugin name */
  1019. /* const char* */
  1020. STRUCT_FLD(name, "INNODB_CMP_RESET"),
  1021. /* plugin author (for SHOW PLUGINS) */
  1022. /* const char* */
  1023. STRUCT_FLD(author, plugin_author),
  1024. /* general descriptive text (for SHOW PLUGINS) */
  1025. /* const char* */
  1026. STRUCT_FLD(descr, "Statistics for the InnoDB compression;"
  1027. " reset cumulated counts"),
  1028. /* the plugin license (PLUGIN_LICENSE_XXX) */
  1029. /* int */
  1030. STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
  1031. /* the function to invoke when plugin is loaded */
  1032. /* int (*)(void*); */
  1033. STRUCT_FLD(init, i_s_cmp_reset_init),
  1034. /* the function to invoke when plugin is unloaded */
  1035. /* int (*)(void*); */
  1036. STRUCT_FLD(deinit, i_s_common_deinit),
  1037. /* plugin version (for SHOW PLUGINS) */
  1038. /* unsigned int */
  1039. STRUCT_FLD(version, INNODB_VERSION_SHORT),
  1040. /* struct st_mysql_show_var* */
  1041. STRUCT_FLD(status_vars, NULL),
  1042. /* struct st_mysql_sys_var** */
  1043. STRUCT_FLD(system_vars, NULL),
  1044. /* reserved for dependency checking */
  1045. /* void* */
  1046. STRUCT_FLD(__reserved1, NULL)
  1047. };
  1048. /* Fields of the dynamic table information_schema.innodb_cmpmem. */
  1049. static ST_FIELD_INFO i_s_cmpmem_fields_info[] =
  1050. {
  1051. {STRUCT_FLD(field_name, "page_size"),
  1052. STRUCT_FLD(field_length, 5),
  1053. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  1054. STRUCT_FLD(value, 0),
  1055. STRUCT_FLD(field_flags, 0),
  1056. STRUCT_FLD(old_name, "Buddy Block Size"),
  1057. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  1058. {STRUCT_FLD(field_name, "pages_used"),
  1059. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  1060. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  1061. STRUCT_FLD(value, 0),
  1062. STRUCT_FLD(field_flags, 0),
  1063. STRUCT_FLD(old_name, "Currently in Use"),
  1064. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  1065. {STRUCT_FLD(field_name, "pages_free"),
  1066. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  1067. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  1068. STRUCT_FLD(value, 0),
  1069. STRUCT_FLD(field_flags, 0),
  1070. STRUCT_FLD(old_name, "Currently Available"),
  1071. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  1072. {STRUCT_FLD(field_name, "relocation_ops"),
  1073. STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
  1074. STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
  1075. STRUCT_FLD(value, 0),
  1076. STRUCT_FLD(field_flags, 0),
  1077. STRUCT_FLD(old_name, "Total Number of Relocations"),
  1078. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  1079. {STRUCT_FLD(field_name, "relocation_time"),
  1080. STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
  1081. STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
  1082. STRUCT_FLD(value, 0),
  1083. STRUCT_FLD(field_flags, 0),
  1084. STRUCT_FLD(old_name, "Total Duration of Relocations,"
  1085. " in Seconds"),
  1086. STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
  1087. END_OF_ST_FIELD_INFO
  1088. };
  1089. /*******************************************************************//**
  1090. Fill the dynamic table information_schema.innodb_cmpmem or
  1091. innodb_cmpmem_reset.
  1092. @return 0 on success, 1 on failure */
  1093. static
  1094. int
  1095. i_s_cmpmem_fill_low(
  1096. /*================*/
  1097. THD* thd, /*!< in: thread */
  1098. TABLE_LIST* tables, /*!< in/out: tables to fill */
  1099. COND* cond, /*!< in: condition (ignored) */
  1100. ibool reset) /*!< in: TRUE=reset cumulated counts */
  1101. {
  1102. TABLE* table = (TABLE *) tables->table;
  1103. int status = 0;
  1104. DBUG_ENTER("i_s_cmpmem_fill_low");
  1105. /* deny access to non-superusers */
  1106. if (check_global_access(thd, PROCESS_ACL)) {
  1107. DBUG_RETURN(0);
  1108. }
  1109. RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
  1110. buf_pool_mutex_enter();
  1111. for (uint x = 0; x <= BUF_BUDDY_SIZES; x++) {
  1112. buf_buddy_stat_t* buddy_stat = &buf_buddy_stat[x];
  1113. table->field[0]->store(BUF_BUDDY_LOW << x);
  1114. table->field[1]->store(buddy_stat->used);
  1115. table->field[2]->store(UNIV_LIKELY(x < BUF_BUDDY_SIZES)
  1116. ? UT_LIST_GET_LEN(buf_pool->zip_free[x])
  1117. : 0);
  1118. table->field[3]->store((longlong) buddy_stat->relocated, true);
  1119. table->field[4]->store(
  1120. (ulong) (buddy_stat->relocated_usec / 1000000));
  1121. if (reset) {
  1122. /* This is protected by buf_pool_mutex. */
  1123. buddy_stat->relocated = 0;
  1124. buddy_stat->relocated_usec = 0;
  1125. }
  1126. if (schema_table_store_record(thd, table)) {
  1127. status = 1;
  1128. break;
  1129. }
  1130. }
  1131. buf_pool_mutex_exit();
  1132. DBUG_RETURN(status);
  1133. }
  1134. /*******************************************************************//**
  1135. Fill the dynamic table information_schema.innodb_cmpmem.
  1136. @return 0 on success, 1 on failure */
  1137. static
  1138. int
  1139. i_s_cmpmem_fill(
  1140. /*============*/
  1141. THD* thd, /*!< in: thread */
  1142. TABLE_LIST* tables, /*!< in/out: tables to fill */
  1143. COND* cond) /*!< in: condition (ignored) */
  1144. {
  1145. return(i_s_cmpmem_fill_low(thd, tables, cond, FALSE));
  1146. }
  1147. /*******************************************************************//**
  1148. Fill the dynamic table information_schema.innodb_cmpmem_reset.
  1149. @return 0 on success, 1 on failure */
  1150. static
  1151. int
  1152. i_s_cmpmem_reset_fill(
  1153. /*==================*/
  1154. THD* thd, /*!< in: thread */
  1155. TABLE_LIST* tables, /*!< in/out: tables to fill */
  1156. COND* cond) /*!< in: condition (ignored) */
  1157. {
  1158. return(i_s_cmpmem_fill_low(thd, tables, cond, TRUE));
  1159. }
  1160. /*******************************************************************//**
  1161. Bind the dynamic table information_schema.innodb_cmpmem.
  1162. @return 0 on success */
  1163. static
  1164. int
  1165. i_s_cmpmem_init(
  1166. /*============*/
  1167. void* p) /*!< in/out: table schema object */
  1168. {
  1169. DBUG_ENTER("i_s_cmpmem_init");
  1170. ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
  1171. schema->fields_info = i_s_cmpmem_fields_info;
  1172. schema->fill_table = i_s_cmpmem_fill;
  1173. DBUG_RETURN(0);
  1174. }
  1175. /*******************************************************************//**
  1176. Bind the dynamic table information_schema.innodb_cmpmem_reset.
  1177. @return 0 on success */
  1178. static
  1179. int
  1180. i_s_cmpmem_reset_init(
  1181. /*==================*/
  1182. void* p) /*!< in/out: table schema object */
  1183. {
  1184. DBUG_ENTER("i_s_cmpmem_reset_init");
  1185. ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
  1186. schema->fields_info = i_s_cmpmem_fields_info;
  1187. schema->fill_table = i_s_cmpmem_reset_fill;
  1188. DBUG_RETURN(0);
  1189. }
  1190. UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem =
  1191. {
  1192. /* the plugin type (a MYSQL_XXX_PLUGIN value) */
  1193. /* int */
  1194. STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
  1195. /* pointer to type-specific plugin descriptor */
  1196. /* void* */
  1197. STRUCT_FLD(info, &i_s_info),
  1198. /* plugin name */
  1199. /* const char* */
  1200. STRUCT_FLD(name, "INNODB_CMPMEM"),
  1201. /* plugin author (for SHOW PLUGINS) */
  1202. /* const char* */
  1203. STRUCT_FLD(author, plugin_author),
  1204. /* general descriptive text (for SHOW PLUGINS) */
  1205. /* const char* */
  1206. STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool"),
  1207. /* the plugin license (PLUGIN_LICENSE_XXX) */
  1208. /* int */
  1209. STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
  1210. /* the function to invoke when plugin is loaded */
  1211. /* int (*)(void*); */
  1212. STRUCT_FLD(init, i_s_cmpmem_init),
  1213. /* the function to invoke when plugin is unloaded */
  1214. /* int (*)(void*); */
  1215. STRUCT_FLD(deinit, i_s_common_deinit),
  1216. /* plugin version (for SHOW PLUGINS) */
  1217. /* unsigned int */
  1218. STRUCT_FLD(version, INNODB_VERSION_SHORT),
  1219. /* struct st_mysql_show_var* */
  1220. STRUCT_FLD(status_vars, NULL),
  1221. /* struct st_mysql_sys_var** */
  1222. STRUCT_FLD(system_vars, NULL),
  1223. /* reserved for dependency checking */
  1224. /* void* */
  1225. STRUCT_FLD(__reserved1, NULL)
  1226. };
  1227. UNIV_INTERN struct st_mysql_plugin i_s_innodb_cmpmem_reset =
  1228. {
  1229. /* the plugin type (a MYSQL_XXX_PLUGIN value) */
  1230. /* int */
  1231. STRUCT_FLD(type, MYSQL_INFORMATION_SCHEMA_PLUGIN),
  1232. /* pointer to type-specific plugin descriptor */
  1233. /* void* */
  1234. STRUCT_FLD(info, &i_s_info),
  1235. /* plugin name */
  1236. /* const char* */
  1237. STRUCT_FLD(name, "INNODB_CMPMEM_RESET"),
  1238. /* plugin author (for SHOW PLUGINS) */
  1239. /* const char* */
  1240. STRUCT_FLD(author, plugin_author),
  1241. /* general descriptive text (for SHOW PLUGINS) */
  1242. /* const char* */
  1243. STRUCT_FLD(descr, "Statistics for the InnoDB compressed buffer pool;"
  1244. " reset cumulated counts"),
  1245. /* the plugin license (PLUGIN_LICENSE_XXX) */
  1246. /* int */
  1247. STRUCT_FLD(license, PLUGIN_LICENSE_GPL),
  1248. /* the function to invoke when plugin is loaded */
  1249. /* int (*)(void*); */
  1250. STRUCT_FLD(init, i_s_cmpmem_reset_init),
  1251. /* the function to invoke when plugin is unloaded */
  1252. /* int (*)(void*); */
  1253. STRUCT_FLD(deinit, i_s_common_deinit),
  1254. /* plugin version (for SHOW PLUGINS) */
  1255. /* unsigned int */
  1256. STRUCT_FLD(version, INNODB_VERSION_SHORT),
  1257. /* struct st_mysql_show_var* */
  1258. STRUCT_FLD(status_vars, NULL),
  1259. /* struct st_mysql_sys_var** */
  1260. STRUCT_FLD(system_vars, NULL),
  1261. /* reserved for dependency checking */
  1262. /* void* */
  1263. STRUCT_FLD(__reserved1, NULL)
  1264. };
  1265. /*******************************************************************//**
  1266. Unbind a dynamic INFORMATION_SCHEMA table.
  1267. @return 0 on success */
  1268. static
  1269. int
  1270. i_s_common_deinit(
  1271. /*==============*/
  1272. void* p) /*!< in/out: table schema object */
  1273. {
  1274. DBUG_ENTER("i_s_common_deinit");
  1275. /* Do nothing */
  1276. DBUG_RETURN(0);
  1277. }