/* Copyright (C) 2013 Kentoku Shiba 2013/08/26 - New columns by Roberto Spadim This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define MYSQL_SERVER 1 #include "mysql_version.h" #include "mysql/plugin.h" #include "sql_class.h" #include "sql_show.h" static I_List *metadata_lock_info_threads; static ST_FIELD_INFO i_s_metadata_lock_info_fields_info[] = { {"THREAD_ID", 20, MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, "thread_id", SKIP_OPEN_TABLE}, {"QUERY_ID", 20, MYSQL_TYPE_LONGLONG, 0, MY_I_S_UNSIGNED, "query_id", SKIP_OPEN_TABLE}, {"LOCK_DURATION", 12, MYSQL_TYPE_STRING, 0, 0, "lock_duration", SKIP_OPEN_TABLE}, {"LOCK_MODE", 24, MYSQL_TYPE_STRING, 0, 0, "lock_mode", SKIP_OPEN_TABLE}, {"LOCK_NAMESPACE", 30, MYSQL_TYPE_STRING, 0, 0, "lock_namespace", SKIP_OPEN_TABLE}, {"KEY", 64, MYSQL_TYPE_STRING, 0, 0, "key", SKIP_OPEN_TABLE}, {"SUB_KEY", 64, MYSQL_TYPE_STRING, 0, 0, "sub_key", SKIP_OPEN_TABLE}, {NULL, 0, MYSQL_TYPE_STRING, 0, 0, NULL, 0} }; static int i_s_metadata_lock_info_fill_table( THD *thd, TABLE_LIST *tables, COND *cond ) { TABLE *table = tables->table; DBUG_ENTER("i_s_metadata_lock_info_fill_table"); mysql_mutex_lock(&LOCK_thread_count); if (!thd->killed) { I_List_iterator thread_it(*metadata_lock_info_threads); THD* tmp_thd; while ((tmp_thd = thread_it++)) { table->field[0]->store((longlong) tmp_thd->thread_id, TRUE); table->field[1]->store((longlong) tmp_thd->query_id, TRUE); MDL_context *mdl_context = &tmp_thd->mdl_context; uint duration; for (duration = MDL_STATEMENT; duration < MDL_DURATION_END; ++duration) { if(duration==MDL_STATEMENT) table->field[2]->store("Statement", 9, system_charset_info); else if(duration==MDL_TRANSACTION) table->field[2]->store("Transaction", 11, system_charset_info); else if(duration==MDL_EXPLICIT) table->field[2]->store("Explicit", 8, system_charset_info); else if(duration==MDL_DURATION_END) table->field[2]->store("Duration END", 12, system_charset_info); else table->field[2]->store("Unknown", 7, system_charset_info); MDL_ticket *mdl_ticket; MDL_context::Ticket_iterator ticket_it( mdl_context->m_tickets[duration]); while ((mdl_ticket = ticket_it++)) { if(mdl_ticket->get_type()==MDL_INTENTION_EXCLUSIVE) table->field[3]->store("MDL_INTENTION_EXCLUSIVE", 23, system_charset_info); else if(mdl_ticket->get_type()==MDL_SHARED) table->field[3]->store("MDL_SHARED", 10, system_charset_info); else if(mdl_ticket->get_type()==MDL_SHARED_HIGH_PRIO) table->field[3]->store("MDL_SHARED_HIGH_PRIO", 20, system_charset_info); else if(mdl_ticket->get_type()==MDL_SHARED_READ) table->field[3]->store("MDL_SHARED_READ", 15, system_charset_info); else if(mdl_ticket->get_type()==MDL_SHARED_WRITE) table->field[3]->store("MDL_SHARED_WRITE", 16, system_charset_info); else if(mdl_ticket->get_type()==MDL_SHARED_UPGRADABLE) table->field[3]->store("MDL_SHARED_UPGRADABLE", 21, system_charset_info); else if(mdl_ticket->get_type()==MDL_SHARED_NO_WRITE) table->field[3]->store("MDL_SHARED_NO_WRITE", 19, system_charset_info); else if(mdl_ticket->get_type()==MDL_SHARED_NO_READ_WRITE) table->field[3]->store("MDL_SHARED_NO_READ_WRITE", 24, system_charset_info); else if(mdl_ticket->get_type()==MDL_EXCLUSIVE) table->field[3]->store("MDL_EXCLUSIVE", 13, system_charset_info); else if(mdl_ticket->get_type()==MDL_TYPE_END) table->field[3]->store("MDL_TYPE_END", 12, system_charset_info); else table->field[3]->store("Unkown", 6, system_charset_info); MDL_key *mdl_key = mdl_ticket->get_key(); if(mdl_key->mdl_namespace()==MDL_key::GLOBAL) table->field[4]->store("Global read lock", 16, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::SCHEMA) table->field[4]->store("Schema metadata lock", 20, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::TABLE) table->field[4]->store("Table metadata lock", 19, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::FUNCTION) table->field[4]->store("Stored function metadata lock", 29, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::PROCEDURE) table->field[4]->store("Stored procedure metadata lock", 30, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::TRIGGER) table->field[4]->store("Trigger metadata lock", 21, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::EVENT) table->field[4]->store("Event metadata lock", 19, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::COMMIT) table->field[4]->store("Commit metadata lock", 20, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::USER_LOCK) table->field[4]->store("User lock", 9, system_charset_info); else if(mdl_key->mdl_namespace()==MDL_key::NAMESPACE_END) table->field[4]->store("NAMESPACE_END", 13, system_charset_info); else table->field[4]->store("Unknown", 7, system_charset_info); table->field[5]->store(mdl_key->db_name(), mdl_key->db_name_length(), system_charset_info); table->field[6]->store(mdl_key->name(), mdl_key->name_length(), system_charset_info); if (schema_table_store_record(thd, table)) { mysql_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(1); } } } } } mysql_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(0); } static int i_s_metadata_lock_info_init( void *p ) { ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *) p; DBUG_ENTER("i_s_metadata_lock_info_init"); schema->fields_info = i_s_metadata_lock_info_fields_info; schema->fill_table = i_s_metadata_lock_info_fill_table; schema->idx_field1 = 0; #ifdef _WIN32 HMODULE current_module = GetModuleHandle(NULL); metadata_lock_info_threads = (I_List *) GetProcAddress(current_module, "?threads@@3V?$I_List@VTHD@@@@A"); #else metadata_lock_info_threads = &threads; #endif DBUG_RETURN(0); } static int i_s_metadata_lock_info_deinit( void *p ) { DBUG_ENTER("i_s_metadata_lock_info_deinit"); DBUG_RETURN(0); } static struct st_mysql_information_schema i_s_metadata_lock_info_plugin = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; #ifdef MARIADB_BASE_VERSION maria_declare_plugin(metadata_lock_info) { MYSQL_INFORMATION_SCHEMA_PLUGIN, &i_s_metadata_lock_info_plugin, "METADATA_LOCK_INFO", "Kentoku Shiba", "Metadata locking viewer", PLUGIN_LICENSE_GPL, i_s_metadata_lock_info_init, i_s_metadata_lock_info_deinit, 0x0001, NULL, NULL, NULL, MariaDB_PLUGIN_MATURITY_ALPHA, } maria_declare_plugin_end; #else mysql_declare_plugin(metadata_lock_info) { MYSQL_INFORMATION_SCHEMA_PLUGIN, &i_s_metadata_lock_info_plugin, "METADATA_LOCK_INFO", "Kentoku Shiba", "Metadata locking viewer", PLUGIN_LICENSE_GPL, i_s_metadata_lock_info_init, i_s_metadata_lock_info_deinit, 0x0001, NULL, NULL, NULL, #if MYSQL_VERSION_ID >= 50600 0, #endif } mysql_declare_plugin_end; #endif