|
- /* Copyright (c) 2008, 2021, Oracle and/or its affiliates.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License, version 2.0,
- as published by the Free Software Foundation.
-
- This program is also distributed with certain software (including
- but not limited to OpenSSL) that is licensed under separate terms,
- as designated in a particular file or component or in included license
- documentation. The authors of MySQL hereby grant you an additional
- permission to link the program and your derivative works with the
- separately licensed software that they have included with MySQL.
-
- 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, version 2.0, 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,
- 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
-
- /**
- @file storage/perfschema/pfs_server.cc
- Private interface for the server (implementation).
- */
-
- #include "my_global.h"
- #include "my_sys.h"
- #include "mysys_err.h"
- #include "pfs_server.h"
- #include "pfs.h"
- #include "pfs_global.h"
- #include "pfs_instr_class.h"
- #include "pfs_builtin_memory.h"
- #include "pfs_instr.h"
- #include "pfs_events_waits.h"
- #include "pfs_events_stages.h"
- #include "pfs_events_statements.h"
- #include "pfs_events_transactions.h"
- #include "pfs_timer.h"
- #include "pfs_setup_actor.h"
- #include "pfs_setup_object.h"
- #include "pfs_host.h"
- #include "pfs_user.h"
- #include "pfs_account.h"
- #include "pfs_defaults.h"
- #include "pfs_digest.h"
- #include "pfs_program.h"
- #include "template_utils.h"
- #include "pfs_prepared_stmt.h"
-
- PFS_global_param pfs_param;
-
- PFS_table_stat PFS_table_stat::g_reset_template;
-
- C_MODE_START
- static void destroy_pfs_thread(void *key);
- C_MODE_END
-
- static void cleanup_performance_schema(void);
- void cleanup_instrument_config(void);
-
- void pre_initialize_performance_schema()
- {
- pfs_initialized= false;
-
- init_all_builtin_memory_class();
-
- PFS_table_stat::g_reset_template.reset();
- global_idle_stat.reset();
- global_table_io_stat.reset();
- global_table_lock_stat.reset();
-
- if (my_create_thread_local_key(&THR_PFS, destroy_pfs_thread))
- return;
- if (my_create_thread_local_key(&THR_PFS_VG, NULL)) // global_variables
- return;
- if (my_create_thread_local_key(&THR_PFS_SV, NULL)) // session_variables
- return;
- if (my_create_thread_local_key(&THR_PFS_VBT, NULL)) // variables_by_thread
- return;
- if (my_create_thread_local_key(&THR_PFS_SG, NULL)) // global_status
- return;
- if (my_create_thread_local_key(&THR_PFS_SS, NULL)) // session_status
- return;
- if (my_create_thread_local_key(&THR_PFS_SBT, NULL)) // status_by_thread
- return;
- if (my_create_thread_local_key(&THR_PFS_SBU, NULL)) // status_by_user
- return;
- if (my_create_thread_local_key(&THR_PFS_SBH, NULL)) // status_by_host
- return;
- if (my_create_thread_local_key(&THR_PFS_SBA, NULL)) // status_by_account
- return;
-
- THR_PFS_initialized= true;
- }
-
- struct PSI_bootstrap*
- initialize_performance_schema(PFS_global_param *param)
- {
- if (!THR_PFS_initialized)
- {
- /* Pre-initialization failed. */
- return NULL;
- }
-
- pfs_enabled= param->m_enabled;
-
- pfs_automated_sizing(param);
- init_timers();
- init_event_name_sizing(param);
- register_global_classes();
-
- if (init_sync_class(param->m_mutex_class_sizing,
- param->m_rwlock_class_sizing,
- param->m_cond_class_sizing) ||
- init_thread_class(param->m_thread_class_sizing) ||
- init_table_share(param->m_table_share_sizing) ||
- init_table_share_lock_stat(param->m_table_lock_stat_sizing) ||
- init_table_share_index_stat(param->m_index_stat_sizing) ||
- init_file_class(param->m_file_class_sizing) ||
- init_stage_class(param->m_stage_class_sizing) ||
- init_statement_class(param->m_statement_class_sizing) ||
- init_socket_class(param->m_socket_class_sizing) ||
- init_memory_class(param->m_memory_class_sizing) ||
- init_instruments(param) ||
- init_events_waits_history_long(
- param->m_events_waits_history_long_sizing) ||
- init_events_stages_history_long(
- param->m_events_stages_history_long_sizing) ||
- init_events_statements_history_long(
- param->m_events_statements_history_long_sizing) ||
- init_events_transactions_history_long(
- param->m_events_transactions_history_long_sizing) ||
- init_file_hash(param) ||
- init_table_share_hash(param) ||
- init_setup_actor(param) ||
- init_setup_actor_hash(param) ||
- init_setup_object(param) ||
- init_setup_object_hash(param) ||
- init_host(param) ||
- init_host_hash(param) ||
- init_user(param) ||
- init_user_hash(param) ||
- init_account(param) ||
- init_account_hash(param) ||
- init_digest(param) ||
- init_digest_hash(param) ||
- init_program(param) ||
- init_program_hash(param) ||
- init_prepared_stmt(param))
- {
- /*
- The performance schema initialization failed.
- Free the memory used, and disable the instrumentation.
- */
- cleanup_performance_schema();
- return NULL;
- }
-
- if (param->m_enabled)
- {
- /** Default values for SETUP_CONSUMERS */
- flag_events_stages_current= param->m_consumer_events_stages_current_enabled;
- flag_events_stages_history= param->m_consumer_events_stages_history_enabled;
- flag_events_stages_history_long= param->m_consumer_events_stages_history_long_enabled;
- flag_events_statements_current= param->m_consumer_events_statements_current_enabled;
- flag_events_statements_history= param->m_consumer_events_statements_history_enabled;
- flag_events_statements_history_long= param->m_consumer_events_statements_history_long_enabled;
- flag_events_transactions_current= param->m_consumer_events_transactions_current_enabled;
- flag_events_transactions_history= param->m_consumer_events_transactions_history_enabled;
- flag_events_transactions_history_long= param->m_consumer_events_transactions_history_long_enabled;
- flag_events_waits_current= param->m_consumer_events_waits_current_enabled;
- flag_events_waits_history= param->m_consumer_events_waits_history_enabled;
- flag_events_waits_history_long= param->m_consumer_events_waits_history_long_enabled;
- flag_global_instrumentation= param->m_consumer_global_instrumentation_enabled;
- flag_thread_instrumentation= param->m_consumer_thread_instrumentation_enabled;
- flag_statements_digest= param->m_consumer_statement_digest_enabled;
- }
- else
- {
- flag_events_stages_current= false;
- flag_events_stages_history= false;
- flag_events_stages_history_long= false;
- flag_events_statements_current= false;
- flag_events_statements_history= false;
- flag_events_statements_history_long= false;
- flag_events_transactions_current= false;
- flag_events_transactions_history= false;
- flag_events_transactions_history_long= false;
- flag_events_waits_current= false;
- flag_events_waits_history= false;
- flag_events_waits_history_long= false;
- flag_global_instrumentation= false;
- flag_thread_instrumentation= false;
- flag_statements_digest= false;
- }
-
- pfs_initialized= true;
-
- if (param->m_enabled)
- {
- install_default_setup(&PFS_bootstrap);
- return &PFS_bootstrap;
- }
-
- return NULL;
- }
-
- static void destroy_pfs_thread(void *key)
- {
- PFS_thread* pfs= reinterpret_cast<PFS_thread*> (key);
- assert(pfs);
- /*
- This automatic cleanup is a last resort and best effort to avoid leaks,
- and may not work on windows due to the implementation of pthread_key_create().
- Please either use:
- - my_thread_end()
- - or PSI_server->delete_current_thread()
- in the instrumented code, to explicitly cleanup the instrumentation.
-
- Avoid invalid writes when the main() thread completes after shutdown:
- the memory pointed by pfs is already released.
- */
- if (pfs_initialized)
- destroy_thread(pfs);
- }
-
- static void cleanup_performance_schema(void)
- {
- /*
- my.cnf options
- */
-
- cleanup_instrument_config();
-
- /*
- All the LF_HASH
- */
-
- cleanup_setup_actor_hash();
- cleanup_setup_object_hash();
- cleanup_account_hash();
- cleanup_host_hash();
- cleanup_user_hash();
- cleanup_program_hash();
- cleanup_table_share_hash();
- cleanup_file_hash();
- cleanup_digest_hash();
-
- /*
- Then the lookup tables
- */
-
- cleanup_setup_actor();
- cleanup_setup_object();
-
- /*
- Then the history tables
- */
-
- cleanup_events_waits_history_long();
- cleanup_events_stages_history_long();
- cleanup_events_statements_history_long();
- cleanup_events_transactions_history_long();
-
- /*
- Then the various aggregations
- */
-
- cleanup_digest();
- cleanup_account();
- cleanup_host();
- cleanup_user();
-
- /*
- Then the instrument classes.
- Once a class is cleaned up,
- find_XXX_class(key)
- will return PSI_NOT_INSTRUMENTED
- */
- cleanup_program();
- cleanup_prepared_stmt();
- cleanup_sync_class();
- cleanup_thread_class();
- cleanup_table_share();
- cleanup_table_share_lock_stat();
- cleanup_table_share_index_stat();
- cleanup_file_class();
- cleanup_stage_class();
- cleanup_statement_class();
- cleanup_socket_class();
- cleanup_memory_class();
-
- cleanup_instruments();
- }
-
- void shutdown_performance_schema(void)
- {
- pfs_initialized= false;
-
- /* disable everything, especially for this thread. */
- flag_events_stages_current= false;
- flag_events_stages_history= false;
- flag_events_stages_history_long= false;
- flag_events_statements_current= false;
- flag_events_statements_history= false;
- flag_events_statements_history_long= false;
- flag_events_transactions_current= false;
- flag_events_transactions_history= false;
- flag_events_transactions_history_long= false;
- flag_events_waits_current= false;
- flag_events_waits_history= false;
- flag_events_waits_history_long= false;
- flag_global_instrumentation= false;
- flag_thread_instrumentation= false;
- flag_statements_digest= false;
-
- global_table_io_class.m_enabled= false;
- global_table_lock_class.m_enabled= false;
- global_idle_class.m_enabled= false;
- global_metadata_class.m_enabled= false;
- global_transaction_class.m_enabled= false;
-
- cleanup_performance_schema();
- /*
- Be careful to not delete un-initialized keys,
- this would affect key 0, which is THR_KEY_mysys,
- */
- if (THR_PFS_initialized)
- {
- my_set_thread_local(THR_PFS, NULL);
- my_set_thread_local(THR_PFS_VG, NULL); // global_variables
- my_set_thread_local(THR_PFS_SV, NULL); // session_variables
- my_set_thread_local(THR_PFS_VBT, NULL); // variables_by_thread
- my_set_thread_local(THR_PFS_SG, NULL); // global_status
- my_set_thread_local(THR_PFS_SS, NULL); // session_status
- my_set_thread_local(THR_PFS_SBT, NULL); // status_by_thread
- my_set_thread_local(THR_PFS_SBU, NULL); // status_by_user
- my_set_thread_local(THR_PFS_SBH, NULL); // status_by_host
- my_set_thread_local(THR_PFS_SBA, NULL); // status_by_account
-
- my_delete_thread_local_key(THR_PFS);
- my_delete_thread_local_key(THR_PFS_VG);
- my_delete_thread_local_key(THR_PFS_SV);
- my_delete_thread_local_key(THR_PFS_VBT);
- my_delete_thread_local_key(THR_PFS_SG);
- my_delete_thread_local_key(THR_PFS_SS);
- my_delete_thread_local_key(THR_PFS_SBT);
- my_delete_thread_local_key(THR_PFS_SBU);
- my_delete_thread_local_key(THR_PFS_SBH);
- my_delete_thread_local_key(THR_PFS_SBA);
-
- THR_PFS_initialized= false;
- }
- }
-
- /**
- Initialize the dynamic array used to hold PFS_INSTRUMENT configuration
- options.
- */
- void init_pfs_instrument_array()
- {
- pfs_instr_config_array= new Pfs_instr_config_array(PSI_NOT_INSTRUMENTED);
- }
-
- /**
- Deallocate the PFS_INSTRUMENT array.
- */
- void cleanup_instrument_config()
- {
- if (pfs_instr_config_array != NULL)
- my_free_container_pointers(*pfs_instr_config_array);
- delete pfs_instr_config_array;
- pfs_instr_config_array= NULL;
- }
-
- /**
- Process one performance_schema_instrument configuration string. Isolate the
- instrument name, evaluate the option value, and store them in a dynamic array.
- Return 'false' for success, 'true' for error.
-
- @param name Instrument name
- @param value Configuration option: 'on', 'off', etc.
- @return 0 for success, non zero for errors
- */
-
- int add_pfs_instr_to_array(const char* name, const char* value)
- {
- size_t name_length= strlen(name);
- size_t value_length= strlen(value);
-
- /* Allocate structure plus string buffers plus null terminators */
- PFS_instr_config* e = (PFS_instr_config*)my_malloc(PSI_NOT_INSTRUMENTED,
- sizeof(PFS_instr_config)
- + name_length + 1 + value_length + 1, MYF(MY_WME));
- if (!e) return 1;
-
- /* Copy the instrument name */
- e->m_name= (char*)e + sizeof(PFS_instr_config);
- memcpy(e->m_name, name, name_length);
- e->m_name_length= (uint)name_length;
- e->m_name[name_length]= '\0';
-
- /* Set flags accordingly */
- if (!my_strcasecmp(&my_charset_latin1, value, "counted"))
- {
- e->m_enabled= true;
- e->m_timed= false;
- }
- else
- if (!my_strcasecmp(&my_charset_latin1, value, "true") ||
- !my_strcasecmp(&my_charset_latin1, value, "on") ||
- !my_strcasecmp(&my_charset_latin1, value, "1") ||
- !my_strcasecmp(&my_charset_latin1, value, "yes"))
- {
- e->m_enabled= true;
- e->m_timed= true;
- }
- else
- if (!my_strcasecmp(&my_charset_latin1, value, "false") ||
- !my_strcasecmp(&my_charset_latin1, value, "off") ||
- !my_strcasecmp(&my_charset_latin1, value, "0") ||
- !my_strcasecmp(&my_charset_latin1, value, "no"))
- {
- e->m_enabled= false;
- e->m_timed= false;
- }
- else
- {
- my_free(e);
- return 1;
- }
-
- /* Add to the array of default startup options */
- if (pfs_instr_config_array->push_back(e))
- {
- my_free(e);
- return 1;
- }
-
- return 0;
- }
|