/* Copyright (c) 2013, Spaempresarial - Brazil, Roberto Spadim http://www.spadim.com.br/ roberto@spadim.com.br All rights reserved. BIG THANKS TO Vladislav Vaintroub FROM MONTYPROGRAM - wlad@montyprogram.com more information about high level design check MDEV-5019 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Roland Bouman nor the names of the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* TODO: CREATE TABLES LOCKS TO DON'T CRASH / REPORT WRONG INFORMATION CREATE UNITS TEST KNOW WHEN WE ARE AT WINDOWS/UNIX TO SELECT THE RIGHT THREAD POOL METHODS IMPLEMENT WINDOWS THREADPOOL INFORMATION SCHEMA SOMETHING ELSE? */ #ifndef MYSQL_SERVER #define MYSQL_SERVER #endif #include // THD #include // ST_SCHEMA_TABLE #include // THD #include #include #include "sql_locale.h" bool schema_table_store_record(THD *thd, TABLE *table); /* table definitions */ /* THREADPOOL_GROUP_INFO */ static ST_FIELD_INFO threadpool_info_group_info_fields[]= { {"GROUP_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Group_ID", SKIP_OPEN_TABLE}, {"THREAD_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Thread_Count", SKIP_OPEN_TABLE}, {"ACTIVE_THREAD_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Active_Thread_Count", SKIP_OPEN_TABLE}, {"CONNECTION_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Connection_Count", SKIP_OPEN_TABLE}, {"IO_EVENT_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 0, "IO_Event_Count", SKIP_OPEN_TABLE}, {"QUEUE_EVENT_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Queue_Event_Count", SKIP_OPEN_TABLE}, {"PERIOD_LAST_THREAD_CREATION_MS", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Period_Last_Thread_Creation_ms", SKIP_OPEN_TABLE}, {"SHUTDOWN", 1, MYSQL_TYPE_STRING, 0, 0, "Shutdown", SKIP_OPEN_TABLE}, /* TODO: ENUM('Y','N') */ {"STALLED", 1, MYSQL_TYPE_STRING, 0, 0, "Stalled", SKIP_OPEN_TABLE}, /* TODO: ENUM('Y','N') */ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} }; /* THREADPOOL_QUEUE */ static ST_FIELD_INFO threadpool_info_queue_fields[]= { {"GROUP_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Group_ID", SKIP_OPEN_TABLE}, {"QUEUE_THREAD_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Queue_Thread_ID", SKIP_OPEN_TABLE}, {"THD_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "THD_ID", SKIP_OPEN_TABLE}, {"THD_QUERY_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "THD_Query_ID", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} }; /* THREADPOOL_THREADS */ static ST_FIELD_INFO threadpool_info_threads_fields[]= { {"GROUP_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Group_ID", SKIP_OPEN_TABLE}, {"THREAD_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Thread_ID", SKIP_OPEN_TABLE}, {"THD_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "THD_ID", SKIP_OPEN_TABLE}, {"THD_QUERY_ID", 4, MYSQL_TYPE_LONGLONG, 0, 0, "THD_Query_ID", SKIP_OPEN_TABLE}, {"EVENT_COUNT", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Event_Count", SKIP_OPEN_TABLE}, {"IS_LISTENER", 1, MYSQL_TYPE_STRING, 0, 0, "Is_Listener", SKIP_OPEN_TABLE}, /* TODO: ENUM('Y','N') */ {"IS_WAITING", 1, MYSQL_TYPE_STRING, 0, 0, "Is_Waiting", SKIP_OPEN_TABLE}, /* TODO: ENUM('Y','N') */ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} }; /* fill tables */ static int threadpool_info_fill_table_group_info(THD* thd, TABLE_LIST* tables, COND* cond) { /* Threadpool_Group_info (from thread_group_t struct) : group id, thread_count, active_thread_count, connection count, microseconds since last thread creation static thread_group_t all_groups[MAX_THREAD_GROUPS]; struct thread_group_t { mysql_mutex_t mutex; connection_queue_t queue; worker_list_t waiting_threads; worker_thread_t *listener; pthread_attr_t *pthread_attr; int pollfd; int thread_count; int active_thread_count; int connection_count; // Stats for the deadlock detection timer routine. int io_event_count; int queue_event_count; ulonglong last_thread_creation_time; int shutdown_pipe[2]; bool shutdown; bool stalled; } MY_ALIGNED(512); */ TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; ulonglong i=0; /* ulonglong to big? maybe uint? */ for(i=0;ifield[0]->store(i+1, 0); /* THREAD_COUNT */ table->field[1]->store(all_groups[i]->thread_count, 0); /* ACTIVE_THREAD_COUNT */ table->field[2]->store(all_groups[i]->active_thread_count, 0); /* CONNECTION_COUNT */ table->field[3]->store(all_groups[i]->connection_count, 0); /* IO_EVENT_COUNT */ table->field[4]->store(all_groups[i]->io_event_count, 0); /* QUEUE_EVENT_COUNT */ table->field[5]->store(all_groups[i]->queue_event_count, 0); /* PERIOD_LAST_THREAD_CREATION_MS */ table->field[6]->store(all_groups[i]->last_thread_creation_time, 0); /* SHUTDOWN */ table->field[7]->store((all_groups[i]->shutdown?'Y':'N'), 1, cs); /* STALLED */ table->field[8]->store((all_groups[i]->stalled?'Y':'N'), 1, cs); if (schema_table_store_record(thd, table)) return 1; } return 0; } static int threadpool_info_fill_table_queue(THD* thd, TABLE_LIST* tables, COND* cond) { /* Threadpool_pending_requests (combined from all “queue” lists in groups): THD id, group id */ TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; ulonglong i,l; /* ulonglong too big? maybe uint? */ for(i=0;iqueue); connection_t *con; while((con= it++)) { /* each queue for this group */ /* GROUP_ID */ table->field[0]->store(i+1, 0); /* QUEUE_THREAD_ID */ table->field[1]->store(l+1, 0); /* THD_ID */ table->field[2]->store(con->thd->thread_id, 0); /* THD_QUERY_ID */ table->field[3]->store(con->thd->query_id, 0); if (schema_table_store_record(thd, table)) return 1; l++; } } return 0; } static int threadpool_info_fill_table_threads(THD* thd, TABLE_LIST* tables, COND* cond) { /* Threadpool_Threads (combined from all waiting_lists in groups and “thread” list): thread id , group id,THD id (0 if currently idle), event_count, is_listener, is_waiting (we do not store OS thread id btw, because there was no need, you could use address of worker_thread_t struct at least temporarily) */ TABLE *table= tables->table; CHARSET_INFO *cs= system_charset_info; ulonglong i,l; /* ulonglong too big? maybe uint? */ for(i=0;iwaiting_threads); worker_thread_t *wthread; while((con= it++)) { /* each queue for this group */ l=0; /* GROUP_ID */ table->field[0]->store(i+1, 0); /* THREAD_ID */ table->field[1]->store(l+1, 0); /* THD_ID */ table->field[2]->store(0, 0); /* TODO */ /* THD_QUERY_ID */ table->field[3]->store(0, 0); /* TODO */ /* EVENT_COUNT */ table->field[4]->store(wthread->event_count, 0); /* IS_LISTENER */ table->field[5]->store("N", 1, cs); /* TODO */ /* IS_WAITING */ table->field[6]->store("N", 1, cs); /* TODO */ if (schema_table_store_record(thd, table)) return 1; l++; } } return 0; } /* inits */ static int threadpool_info_plugin_init_threads(void *p) { ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; schema->fields_info= threadpool_info_threads_fields; schema->fill_table= threadpool_info_fill_table_threads; return 0; } static int threadpool_info_plugin_init_queue(void *p) { ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; schema->fields_info= threadpool_info_queue_fields; schema->fill_table= threadpool_info_fill_table_queue; return 0; } static int threadpool_info_plugin_init_group_info(void *p) { ST_SCHEMA_TABLE *schema= (ST_SCHEMA_TABLE *)p; schema->fields_info= threadpool_info_group_info_fields; schema->fill_table= threadpool_info_fill_table_group_info; return 0; } static struct st_mysql_information_schema threadpool_info_plugin= { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; /* Plugin library descriptor */ maria_declare_plugin(threadpool_info) { MYSQL_INFORMATION_SCHEMA_PLUGIN, /* the plugin type (see include/mysql/plugin.h) */ &threadpool_info_plugin, /* pointer to type-specific plugin descriptor */ "THREADPOOL_THREADS", /* plugin name */ "Roberto Spadim, Spaempresarial - Brazil", /* plugin author */ "Group of threads - threadpool.", /* the plugin description */ PLUGIN_LICENSE_BSD, /* the plugin license (see include/mysql/plugin.h) */ threadpool_info_plugin_init_threads, /* Pointer to plugin initialization function */ 0, /* Pointer to plugin deinitialization function */ 0x0100, /* Numeric version 0xAABB means AA.BB veriosn */ NULL, /* Status variables */ NULL, /* System variables */ "1.0", /* String version representation */ MariaDB_PLUGIN_MATURITY_ALPHA /* Maturity (see include/mysql/plugin.h)*/ }, { MYSQL_INFORMATION_SCHEMA_PLUGIN, /* the plugin type (see include/mysql/plugin.h) */ &threadpool_info_plugin, /* pointer to type-specific plugin descriptor */ "THREADPOOL_QUEUE", /* plugin name */ "Roberto Spadim, Spaempresarial - Brazil", /* plugin author */ "Pending Requests - threadpool.", /* the plugin description */ PLUGIN_LICENSE_BSD, /* the plugin license (see include/mysql/plugin.h) */ threadpool_info_plugin_init_queue, /* Pointer to plugin initialization function */ 0, /* Pointer to plugin deinitialization function */ 0x0100, /* Numeric version 0xAABB means AA.BB veriosn */ NULL, /* Status variables */ NULL, /* System variables */ "1.0", /* String version representation */ MariaDB_PLUGIN_MATURITY_ALPHA /* Maturity (see include/mysql/plugin.h)*/ }, { MYSQL_INFORMATION_SCHEMA_PLUGIN, /* the plugin type (see include/mysql/plugin.h) */ &threadpool_info_plugin, /* pointer to type-specific plugin descriptor */ "THREADPOOL_GROUP_INFO", /* plugin name */ "Roberto Spadim, Spaempresarial - Brazil", /* plugin author */ "Thread Groups info - threadpool.", /* the plugin description */ PLUGIN_LICENSE_BSD, /* the plugin license (see include/mysql/plugin.h) */ threadpool_info_plugin_init_group_info, /* Pointer to plugin initialization function */ 0, /* Pointer to plugin deinitialization function */ 0x0100, /* Numeric version 0xAABB means AA.BB veriosn */ NULL, /* Status variables */ NULL, /* System variables */ "1.0", /* String version representation */ MariaDB_PLUGIN_MATURITY_ALPHA /* Maturity (see include/mysql/plugin.h)*/ } maria_declare_plugin_end;