mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
311 lines
9.6 KiB
C++
311 lines
9.6 KiB
C++
/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
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, Fifth Floor, 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_instr.h"
|
|
#include "pfs_events_waits.h"
|
|
#include "pfs_events_stages.h"
|
|
#include "pfs_events_statements.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"
|
|
|
|
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);
|
|
|
|
struct PSI_bootstrap*
|
|
initialize_performance_schema(PFS_global_param *param)
|
|
{
|
|
pfs_initialized= false;
|
|
|
|
PFS_table_stat::g_reset_template.reset();
|
|
global_idle_stat.reset();
|
|
global_table_io_stat.reset();
|
|
global_table_lock_stat.reset();
|
|
|
|
pfs_automated_sizing(param);
|
|
|
|
if (! param->m_enabled)
|
|
{
|
|
/*
|
|
The performance schema is disabled in the startup command line.
|
|
All the instrumentation is turned off.
|
|
*/
|
|
pfs_enabled= 0;
|
|
return NULL;
|
|
}
|
|
pfs_enabled= TRUE;
|
|
|
|
init_timers();
|
|
|
|
init_event_name_sizing(param);
|
|
register_global_classes();
|
|
|
|
if (pthread_key_create(&THR_PFS, destroy_pfs_thread))
|
|
return NULL;
|
|
|
|
THR_PFS_initialized= true;
|
|
|
|
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_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_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_file_hash() ||
|
|
init_table_share_hash() ||
|
|
init_setup_actor(param) ||
|
|
init_setup_actor_hash() ||
|
|
init_setup_object(param) ||
|
|
init_setup_object_hash() ||
|
|
init_host(param) ||
|
|
init_host_hash() ||
|
|
init_user(param) ||
|
|
init_user_hash() ||
|
|
init_account(param) ||
|
|
init_account_hash() ||
|
|
init_digest(param) ||
|
|
init_digest_hash())
|
|
{
|
|
/*
|
|
The performance schema initialization failed.
|
|
Free the memory used, and disable the instrumentation.
|
|
*/
|
|
cleanup_performance_schema();
|
|
return NULL;
|
|
}
|
|
|
|
pfs_initialized= true;
|
|
|
|
/** 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_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;
|
|
|
|
install_default_setup(&PFS_bootstrap);
|
|
return &PFS_bootstrap;
|
|
}
|
|
|
|
static void destroy_pfs_thread(void *key)
|
|
{
|
|
PFS_thread* pfs= reinterpret_cast<PFS_thread*> (key);
|
|
DBUG_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)
|
|
{
|
|
cleanup_instrument_config();
|
|
cleanup_instruments();
|
|
cleanup_sync_class();
|
|
cleanup_thread_class();
|
|
cleanup_table_share();
|
|
cleanup_file_class();
|
|
cleanup_stage_class();
|
|
cleanup_statement_class();
|
|
cleanup_socket_class();
|
|
cleanup_events_waits_history_long();
|
|
cleanup_events_stages_history_long();
|
|
cleanup_events_statements_history_long();
|
|
cleanup_table_share_hash();
|
|
cleanup_file_hash();
|
|
cleanup_setup_actor();
|
|
cleanup_setup_actor_hash();
|
|
cleanup_setup_object();
|
|
cleanup_setup_object_hash();
|
|
cleanup_host();
|
|
cleanup_host_hash();
|
|
cleanup_user();
|
|
cleanup_user_hash();
|
|
cleanup_account();
|
|
cleanup_account_hash();
|
|
cleanup_digest();
|
|
cleanup_digest_hash();
|
|
}
|
|
|
|
void shutdown_performance_schema(void)
|
|
{
|
|
pfs_initialized= false;
|
|
cleanup_performance_schema();
|
|
#if 0
|
|
/*
|
|
Be careful to not delete un-initialized keys,
|
|
this would affect key 0, which is THR_KEY_mysys,
|
|
*/
|
|
if (THR_PFS_initialized)
|
|
{
|
|
my_pthread_setspecific_ptr(THR_PFS, NULL);
|
|
pthread_key_delete(THR_PFS);
|
|
THR_PFS_initialized= false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
Initialize the dynamic array used to hold PFS_INSTRUMENT configuration
|
|
options.
|
|
*/
|
|
void init_pfs_instrument_array()
|
|
{
|
|
my_init_dynamic_array(&pfs_instr_config_array, sizeof(PFS_instr_config*),
|
|
10, 10, MYF(0));
|
|
pfs_instr_config_state= PFS_INSTR_CONFIG_ALLOCATED;
|
|
}
|
|
|
|
/**
|
|
Deallocate the PFS_INSTRUMENT array. Use an atomic compare-and-swap to ensure
|
|
that it is deallocated only once in the chaotic environment of server shutdown.
|
|
*/
|
|
void cleanup_instrument_config()
|
|
{
|
|
int desired_state= PFS_INSTR_CONFIG_ALLOCATED;
|
|
|
|
/* Ignore if another thread has already deallocated the array */
|
|
if (my_atomic_cas32(&pfs_instr_config_state, &desired_state, PFS_INSTR_CONFIG_DEALLOCATED))
|
|
{
|
|
PFS_instr_config **array=dynamic_element(&pfs_instr_config_array, 0, PFS_instr_config**);
|
|
for (uint i=0; i < pfs_instr_config_array.elements; i++)
|
|
my_free(array[i]);
|
|
delete_dynamic(&pfs_instr_config_array);
|
|
}
|
|
}
|
|
|
|
/**
|
|
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(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 (insert_dynamic(&pfs_instr_config_array, &e))
|
|
{
|
|
my_free(e);
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|