Quelle pfs_variable.h Sprache: unbekannt
/* Copyright (c) 2015, 2023, 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, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
#ifndef PFS_VARIABLE_H
#define PFS_VARIABLE_H
/**
@ file storage / perfschema / pfs_variable . h
Performance schema system and status variables ( declarations ) .
*/
/**
OVERVIEW
- - - - - - - -
Status and system variables are implemented differently in the server , but the
steps to process them in the Performance Schema are essentially the same :
1 . INITIALIZE - Build or acquire a sorted list of variables to use for input .
Use the SHOW_VAR struct as an intermediate format common to system , status
and user vars :
SHOW_VAR
Name - Text string
Value - Pointer to memory location , function , subarray structure
Type - Scalar , function , or subarray
Scope - SESSION , GLOBAL , BOTH
Steps :
- Register the server ' s internal buffer with the class . Acquire locks
if necessary , then scan the contents of the input buffer .
- For system variables , convert each element to SHOW_VAR format , store in
a temporary array .
- For status variables , copy existing global status array into a local
array that can be used without locks . Expand nested subarrays , indicated
by a type of SHOW_ARRAY .
2 . MATERIALIZE - Convert the list of SHOW_VAR variables to string format ,
store in a local cache :
- Resolve each variable according to the type .
- Recursively process unexpanded nested arrays and callback functions .
- Aggregate values across threads for global status .
- Convert numeric values to a string .
- Prefix variable name with the plugin name .
3 . OUTPUT - Iterate the cache for the SHOW command or table query .
CLASS OVERVIEW
- - - - - - - - - - - - - -
1 . System_variable - A materialized system variable
2 . Status_variable - A materialized status variable
3 . PFS_variable_cache - Base class that defines the interface for the operations above .
public
init_show_var_array ( ) - Build SHOW_VAR list of variables for processing
materialize_global ( ) - Materialize global variables , aggregate across sessions
materialize_session ( ) - Materialize variables for a given PFS_thread or THD
materialize_user ( ) - Materialize variables for a user , aggregate across related threads .
materialize_host ( ) - Materialize variables for a host , aggregate across related threads .
materialize_account ( ) - Materialize variables for a account , aggregate across related threads .
private
m_show_var_array - Prealloc_array of SHOW_VARs for input to Materialize
m_cache - Prealloc_array of materialized variables for output
do_materialize_global ( ) - Implementation of materialize_global ( )
do_materialize_session ( ) - Implementation of materialize_session ( )
do_materialize_client ( ) - Implementation of materialize_user / host / account ( )
4 . PFS_system_variable_cache - System variable implementation of PFS_variable_cache
5 . PFS_status_variable_cache - Status variable implementation of PFS_variable_cache
6 . Find_THD_variable - Used by the thread manager to find and lock a THD .
GLOSSARY
- - - - - - - -
Status variable - Server or plugin status counter . Not dynamic .
System variable - Server or plugin configuration variable . Usually dynamic .
GLOBAL scope - Associated with the server , no context at thread level .
SESSION scope - Associated with a connection or thread , but no global context .
BOTH scope - Globally defined but applies at the session level .
Initialize - Build list of variables in SHOW_VAR format .
Materialize - Convert variables in SHOW_VAR list to string , cache for output .
Manifest - Substep of Materialize . Resolve variable values according to
type . This includes SHOW_FUNC types which are resolved by
executing a callback function ( possibly recursively ) , and
SHOW_ARRAY types that expand into nested subarrays .
LOCK PRIORITIES
- - - - - - - - - - - - - - -
System Variables
LOCK_plugin_delete ( block plugin delete )
LOCK_system_variables_hash
LOCK_thd_data ( block THD delete )
LOCK_thd_sysvar ( block system variable updates , alloc_and_copy_thd_dynamic_variables )
LOCK_global_system_variables ( very briefly held )
Status Variables
LOCK_status
LOCK_thd_data ( block THD delete )
*/
/* Iteration on THD from the sql layer. */
#include "mysqld_thd_manager.h"
#define PFS_VAR
/* Class sys_var */
#include "set_var.h"
/* convert_value_to_string */
#include "sql_show.h"
/* PFS_thread */
#include "pfs_instr.h"
#include "pfs_user.h"
#include "pfs_host.h"
#include "pfs_account.h"
/* Global array of all server and plugin-defined status variables. */
extern DYNAMIC_ARRAY all_status_vars;
extern bool status_vars_inited;
static const uint SYSVAR_MEMROOT_BLOCK_SIZE = 4096 ;
extern mysql_mutex_t LOCK_plugin_delete;
class Find_THD_Impl;
class Find_THD_variable;
typedef PFS_connection_slice PFS_client;
/**
CLASS System_variable - System variable derived from sys_var object .
*/
class System_variable
{
public :
System_variable();
System_variable(THD *target_thd, const SHOW_VAR *show_var,
enum_var_type query_scope, bool ignore);
~System_variable() {}
bool is_null() const { return !m_initialized; }
bool is_ignored() const { return m_ignore; }
public :
const char *m_name;
size_t m_name_length;
char m_value_str[SHOW_VAR_FUNC_BUFF_SIZE+1 ];
size_t m_value_length;
enum_mysql_show_type m_type;
int m_scope;
bool m_ignore;
const CHARSET_INFO *m_charset;
private :
bool m_initialized;
void init(THD *thd, const SHOW_VAR *show_var, enum_var_type query_scope);
};
/**
CLASS Status_variable - Status variable derived from SHOW_VAR .
*/
class Status_variable
{
public :
Status_variable() : m_name(NULL), m_name_length(0 ), m_value_length(0 ),
m_type(SHOW_UNDEF),
m_charset(NULL), m_initialized(false ) {}
Status_variable(const SHOW_VAR *show_var, STATUS_VAR *status_array, enum_var_type query_scope);
~Status_variable() {}
bool is_null() const {return !m_initialized;};
public :
const char *m_name;
size_t m_name_length;
char m_value_str[SHOW_VAR_FUNC_BUFF_SIZE+1 ];
size_t m_value_length;
SHOW_TYPE m_type;
const CHARSET_INFO *m_charset;
private :
bool m_initialized;
void init(const SHOW_VAR *show_var, STATUS_VAR *status_array, enum_var_type query_scope);
};
/**
CLASS Find_THD_variable - Get and lock a validated THD from the thread manager .
*/
class Find_THD_variable : public Find_THD_Impl
{
public :
Find_THD_variable() : m_unsafe_thd(NULL) {}
Find_THD_variable(THD *unsafe_thd) : m_unsafe_thd(unsafe_thd) {}
bool operator ()(THD *thd) override
{
//TODO: filter bg threads?
if (thd != m_unsafe_thd)
return false ;
/*
Hold this lock to keep THD during materialization .
But don ' t lock current_thd ( to be able to use set_killed ( ) later
*/
if (thd != current_thd)
mysql_mutex_lock(&thd->LOCK_thd_kill);
return true ;
}
void set_unsafe_thd(THD *unsafe_thd) { m_unsafe_thd= unsafe_thd; }
private :
THD *m_unsafe_thd;
};
/**
CLASS PFS_variable_cache - Base class for a system or status variable cache .
*/
template <class Var_type>
class PFS_variable_cache
{
public :
typedef Dynamic_array<Var_type> Variable_array;
PFS_variable_cache(bool external_init)
: m_safe_thd(NULL),
m_unsafe_thd(NULL),
m_current_thd(current_thd),
m_pfs_thread(NULL),
m_pfs_client(NULL),
m_thd_finder(),
m_cache(PSI_INSTRUMENT_MEM),
m_initialized(false ),
m_external_init(external_init),
m_materialized(false ),
m_show_var_array(PSI_INSTRUMENT_MEM),
m_version(0 ),
m_query_scope(OPT_DEFAULT),
m_use_mem_root(false ),
m_aggregate(false )
{ }
virtual ~PFS_variable_cache()= 0 ;
/**
Build array of SHOW_VARs from the external variable source .
Filter using session scope .
*/
bool initialize_session(void );
/**
Build array of SHOW_VARs suitable for aggregation by user , host or account .
Filter using session scope .
*/
bool initialize_client_session(void );
/**
Build cache of GLOBAL system or status variables .
Aggregate across threads if applicable .
*/
int materialize_global();
/**
Build cache of GLOBAL and SESSION variables for a non - instrumented thread .
*/
int materialize_all(THD *thd);
/**
Build cache of SESSION variables for a non - instrumented thread .
*/
int materialize_session(THD *thd);
/**
Build cache of SESSION variables for an instrumented thread .
*/
int materialize_session(PFS_thread *pfs_thread, bool use_mem_root= false );
/**
Cache a single SESSION variable for an instrumented thread .
*/
int materialize_session(PFS_thread *pfs_thread, uint index);
/**
Build cache of SESSION status variables for a user .
*/
int materialize_user(PFS_user *pfs_user);
/**
Build cache of SESSION status variables for a host .
*/
int materialize_host(PFS_host *pfs_host);
/**
Build cache of SESSION status variables for an account .
*/
int materialize_account(PFS_account *pfs_account);
/**
True if variables have been materialized .
*/
bool is_materialized(void )
{
return m_materialized;
}
/**
True if variables have been materialized for given THD .
*/
bool is_materialized(THD *unsafe_thd)
{
return (unsafe_thd == m_unsafe_thd && m_materialized);
}
/**
True if variables have been materialized for given PFS_thread .
*/
bool is_materialized(PFS_thread *pfs_thread)
{
return (pfs_thread == m_pfs_thread && m_materialized);
}
/**
True if variables have been materialized for given PFS_user .
*/
bool is_materialized(PFS_user *pfs_user)
{
return (static_cast <PFS_client *>(pfs_user) == m_pfs_client && m_materialized);
}
/**
True if variables have been materialized for given PFS_host .
*/
bool is_materialized(PFS_host *pfs_host)
{
return (static_cast <PFS_client *>(pfs_host) == m_pfs_client && m_materialized);
}
/**
True if variables have been materialized for given PFS_account .
*/
bool is_materialized(PFS_account *pfs_account)
{
return (static_cast <PFS_client *>(pfs_account) == m_pfs_client && m_materialized);
}
/**
True if variables have been materialized for given PFS_user / host / account .
*/
bool is_materialized(PFS_client *pfs_client)
{
return (static_cast <PFS_client *>(pfs_client) == m_pfs_client && m_materialized);
}
/**
Get a validated THD from the thread manager . Execute callback function while
inside of the thread manager locks .
*/
THD *get_THD(THD *thd);
THD *get_THD(PFS_thread *pfs_thread);
/**
Get a single variable from the cache .
Get the first element in the cache by default .
*/
const Var_type *get(uint index= 0 ) const
{
if (index >= m_cache.elements())
return NULL;
const Var_type *p= &m_cache.at(index);
return p;
}
/**
Number of elements in the cache .
*/
uint size()
{
return (uint)m_cache.elements();
}
private :
virtual bool do_initialize_global(void ) { return true ; }
virtual bool do_initialize_session(void ) { return true ; }
virtual int do_materialize_global(void ) { return 1 ; }
virtual int do_materialize_all(THD *thd) { return 1 ; }
virtual int do_materialize_session(THD *thd) { return 1 ; }
virtual int do_materialize_session(PFS_thread *) { return 1 ; }
virtual int do_materialize_session(PFS_thread *, uint index) { return 1 ; }
protected :
/* Validated THD */
THD *m_safe_thd;
/* Unvalidated THD */
THD *m_unsafe_thd;
/* Current THD */
THD *m_current_thd;
/* Current PFS_thread. */
PFS_thread *m_pfs_thread;
/* Current PFS_user, host or account. */
PFS_client *m_pfs_client;
/* Callback for thread iterator. */
Find_THD_variable m_thd_finder;
/* Cache of materialized variables. */
Variable_array m_cache;
/* True when list of SHOW_VAR is complete. */
bool m_initialized;
/*
True if the SHOW_VAR array must be initialized externally from the
materialization step , such as with aggregations and queries by thread .
*/
bool m_external_init;
/* True when cache is complete. */
bool m_materialized;
/* Array of variables to be materialized. Last element must be null. */
Dynamic_array<SHOW_VAR> m_show_var_array;
/* Version of global hash/array. Changes when vars added/removed. */
ulonglong m_version;
/* Query scope: GLOBAL or SESSION. */
enum_var_type m_query_scope;
/* True if temporary mem_root should be used for materialization. */
bool m_use_mem_root;
/* True if summarizing across users, hosts or accounts. */
bool m_aggregate;
};
/**
Required implementation for pure virtual destructor of a template class .
*/
template <class Var_type>
PFS_variable_cache<Var_type>::~PFS_variable_cache()
{
}
/**
Get a validated THD from the thread manager . Execute callback function while
while inside the thread manager lock .
*/
template <class Var_type>
THD *PFS_variable_cache<Var_type>::get_THD(THD *unsafe_thd)
{
if (unsafe_thd == NULL)
{
/*
May happen , precisely because the pointer is unsafe
( THD just disconnected for example ) .
No need to walk Global_THD_manager for that .
*/
return NULL;
}
m_thd_finder.set_unsafe_thd(unsafe_thd);
THD* safe_thd= Global_THD_manager::get_instance()->find_thd(&m_thd_finder);
return safe_thd;
}
template <class Var_type>
THD *PFS_variable_cache<Var_type>::get_THD(PFS_thread *pfs_thread)
{
assert(pfs_thread != NULL);
return get_THD(pfs_thread->m_thd);
}
/**
Build array of SHOW_VARs from external source of system or status variables .
Filter using session scope .
*/
template <class Var_type>
bool PFS_variable_cache<Var_type>::initialize_session(void )
{
if (m_initialized)
return 0 ;
return do_initialize_session();
}
/**
Build array of SHOW_VARs suitable for aggregation by user , host or account .
Filter using session scope .
*/
template <class Var_type>
bool PFS_variable_cache<Var_type>::initialize_client_session(void )
{
if (m_initialized)
return 0 ;
/* Requires aggregation by user, host or account. */
m_aggregate= true ;
return do_initialize_session();
}
/**
Build cache of all GLOBAL variables .
*/
template <class Var_type>
int PFS_variable_cache<Var_type>::materialize_global()
{
if (is_materialized())
return 0 ;
return do_materialize_global();
}
/**
Build cache of GLOBAL and SESSION variables for a non - instrumented thread .
*/
template <class Var_type>
int PFS_variable_cache<Var_type>::materialize_all(THD *unsafe_thd)
{
if (!unsafe_thd)
return 1 ;
if (is_materialized(unsafe_thd))
return 0 ;
return do_materialize_all(unsafe_thd);
}
/**
Build cache of SESSION variables for a non - instrumented thread .
*/
template <class Var_type>
int PFS_variable_cache<Var_type>::materialize_session(THD *unsafe_thd)
{
if (!unsafe_thd)
return 1 ;
if (is_materialized(unsafe_thd))
return 0 ;
return do_materialize_session(unsafe_thd);
}
/**
Build cache of SESSION variables for a thread .
*/
template <class Var_type>
int PFS_variable_cache<Var_type>::materialize_session(PFS_thread *pfs_thread, bool use_mem_root)
{
if (!pfs_thread)
return 1 ;
if (is_materialized(pfs_thread))
return 0 ;
if (!pfs_thread->m_lock.is_populated() || pfs_thread->m_thd == NULL)
return 1 ;
m_use_mem_root= use_mem_root;
return do_materialize_session(pfs_thread);
}
/**
Materialize a single variable for a thread .
*/
template <class Var_type>
int PFS_variable_cache<Var_type>::materialize_session(PFS_thread *pfs_thread, uint index)
{
/* No check for is_materialized(). */
if (!pfs_thread)
return 1 ;
if (!pfs_thread->m_lock.is_populated() || pfs_thread->m_thd == NULL)
return 1 ;
return do_materialize_session(pfs_thread, index);
}
/**
CLASS PFS_system_variable_cache - System variable cache .
*/
class PFS_system_variable_cache : public PFS_variable_cache<System_variable>
{
public :
PFS_system_variable_cache(bool external_init) :
PFS_variable_cache<System_variable>(external_init),
m_mem_thd(NULL), m_mem_thd_save(NULL),
m_mem_sysvar_ptr(NULL) { }
bool match_scope(int scope);
ulonglong get_sysvar_hash_version(void ) { return m_version; }
~PFS_system_variable_cache() { free_mem_root(); }
private :
/* Build SHOW_var array. */
bool init_show_var_array(enum_var_type scope, bool strict);
bool do_initialize_session(void ) override;
/* Global */
int do_materialize_global(void ) override;
/* Global and Session - THD */
int do_materialize_all(THD* thd) override;
/* Session - THD */
int do_materialize_session(THD* thd) override;
/* Session - PFS_thread */
int do_materialize_session(PFS_thread *thread) override;
/* Single variable - PFS_thread */
int do_materialize_session(PFS_thread *pfs_thread, uint index) override;
/* Temporary mem_root to use for materialization. */
MEM_ROOT m_mem_sysvar;
/* Pointer to THD::mem_root. */
MEM_ROOT **m_mem_thd;
/* Save THD::mem_root. */
MEM_ROOT *m_mem_thd_save;
/* Pointer to temporary mem_root. */
MEM_ROOT *m_mem_sysvar_ptr;
/* Allocate and/or assign temporary mem_root. */
void set_mem_root(void );
/* Mark all memory blocks as free in temporary mem_root. */
void clear_mem_root(void );
/* Free mem_root memory. */
void free_mem_root(void );
};
/**
CLASS PFS_status_variable_cache - Status variable cache
*/
class PFS_status_variable_cache : public PFS_variable_cache<Status_variable>
{
public :
PFS_status_variable_cache(bool external_init);
int materialize_user(PFS_user *pfs_user);
int materialize_host(PFS_host *pfs_host);
int materialize_account(PFS_account *pfs_account);
ulonglong get_status_array_version(void ) { return m_version; }
protected :
/* Get PFS_user, account or host associated with a PFS_thread. Implemented by table class. */
virtual PFS_client *get_pfs(PFS_thread *pfs_thread) { return NULL; }
/* True if query is a SHOW command. */
bool m_show_command;
private :
bool do_initialize_session(void ) override;
int do_materialize_global(void ) override;
/* Global and Session - THD */
int do_materialize_all(THD* thd) override;
int do_materialize_session(THD *thd) override;
int do_materialize_session(PFS_thread *thread) override;
int do_materialize_session(PFS_thread *thread, uint index) override { return 0 ; }
int do_materialize_client(PFS_client *pfs_client);
/* Callback to sum user, host or account status variables. */
void (*m_sum_client_status)(PFS_client *pfs_client, STATUS_VAR *status_totals);
/* Build SHOW_VAR array from external source. */
bool init_show_var_array(enum_var_type scope, bool strict);
/* Recursively expand nested SHOW_VAR arrays. */
void expand_show_var_array(const SHOW_VAR *show_var_array, const char *prefix, bool strict);
/* Exclude unwanted variables from the query. */
bool filter_show_var(const SHOW_VAR *show_var, bool strict);
/* Check the variable scope against the query scope. */
bool match_scope(SHOW_SCOPE variable_scope, bool strict);
/* Exclude specific status variables by name or prefix. */
bool filter_by_name(const SHOW_VAR *show_var);
/* Check if a variable has an aggregatable type. */
bool can_aggregate(enum_mysql_show_type variable_type);
/* Build status variable name with prefix. Return in the buffer provided. */
char *make_show_var_name(const char * prefix, const char * name, char *name_buf, size_t buf_len);
/* Build status variable name with prefix. Return copy of the string. */
char *make_show_var_name(const char * prefix, const char * name);
/* For the current THD, use initial_status_vars taken from before the query start. */
STATUS_VAR *set_status_vars(void );
/* Build the list of status variables from SHOW_VAR array. */
void manifest(THD *thd, const SHOW_VAR *show_var_array,
STATUS_VAR *status_var_array, const char *prefix, bool nested_array, bool strict);
};
/* Callback functions to sum status variables for a given user, host or account. */
void sum_user_status(PFS_client *pfs_user, STATUS_VAR *status_totals);
void sum_host_status(PFS_client *pfs_host, STATUS_VAR *status_totals);
void sum_account_status(PFS_client *pfs_account, STATUS_VAR *status_totals);
/** @} */
#endif
Messung V0.5 in Prozent C=88 H=100 G=94
[Seitenstruktur0.18Druckenetwas mehr zur Ethik2026-10-08]
2026-10-09