mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
1291 lines
37 KiB
C++
1291 lines
37 KiB
C++
/* Copyright (c) 2015, 2023, Oracle and/or its affiliates.
|
|
Copyright (c) 2020, MariaDB Corporation.
|
|
|
|
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 */
|
|
|
|
/**
|
|
@file storage/perfschema/pfs_variable.cc
|
|
Performance schema system variable and status variable (implementation).
|
|
*/
|
|
#include "sql_plugin.h"
|
|
#include "pfs_variable.h"
|
|
#include "my_sys.h"
|
|
#include "debug_sync.h"
|
|
#include "pfs.h"
|
|
#include "pfs_global.h"
|
|
#include "pfs_visitor.h"
|
|
#include "sql_audit.h" // audit_global_variable_get
|
|
|
|
static inline SHOW_SCOPE show_scope_from_type(enum enum_mysql_show_type type)
|
|
{
|
|
switch(type) {
|
|
case SHOW_BOOL:
|
|
case SHOW_CHAR:
|
|
case SHOW_CHAR_PTR:
|
|
case SHOW_DOUBLE:
|
|
case SHOW_HAVE:
|
|
case SHOW_HA_ROWS:
|
|
case SHOW_KEY_CACHE_LONG:
|
|
case SHOW_LEX_STRING:
|
|
case SHOW_LONG_NOFLUSH:
|
|
case SHOW_MY_BOOL:
|
|
case SHOW_SINT:
|
|
case SHOW_SLONG:
|
|
case SHOW_SLONGLONG:
|
|
case SHOW_SYS:
|
|
case SHOW_UINT:
|
|
case SHOW_ULONG:
|
|
case SHOW_ULONGLONG:
|
|
return SHOW_SCOPE_GLOBAL;
|
|
|
|
case SHOW_DOUBLE_STATUS:
|
|
case SHOW_LONGLONG_STATUS:
|
|
case SHOW_LONG_STATUS:
|
|
return SHOW_SCOPE_ALL;
|
|
|
|
case SHOW_ARRAY:
|
|
case SHOW_FUNC:
|
|
case SHOW_SIMPLE_FUNC:
|
|
case SHOW_UNDEF:
|
|
default:
|
|
return SHOW_SCOPE_UNDEF;
|
|
}
|
|
return SHOW_SCOPE_UNDEF;
|
|
}
|
|
|
|
|
|
/**
|
|
CLASS PFS_system_variable_cache
|
|
*/
|
|
|
|
/**
|
|
Build a sorted list of all system variables from the system variable hash.
|
|
Filter by scope. Must be called inside of LOCK_plugin_delete.
|
|
*/
|
|
bool PFS_system_variable_cache::init_show_var_array(enum_var_type scope, bool strict)
|
|
{
|
|
assert(!m_initialized);
|
|
m_query_scope= scope;
|
|
|
|
mysql_prlock_rdlock(&LOCK_system_variables_hash);
|
|
DEBUG_SYNC(m_current_thd, "acquired_LOCK_system_variables_hash");
|
|
|
|
/* Record the system variable hash version to detect subsequent changes. */
|
|
m_version= get_system_variable_hash_version();
|
|
|
|
/* Build the SHOW_VAR array from the system variable hash. */
|
|
SHOW_VAR *vars= enumerate_sys_vars(m_current_thd, true, m_query_scope/*, strict */);
|
|
m_show_var_array.reserve(get_system_variable_hash_records());
|
|
for (int i=0; vars[i].name; i++)
|
|
m_show_var_array.set(i, vars[i]);
|
|
|
|
mysql_prlock_unlock(&LOCK_system_variables_hash);
|
|
|
|
/* Increase cache size if necessary. */
|
|
m_cache.reserve(m_show_var_array.elements());
|
|
|
|
m_initialized= true;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
Build an array of SHOW_VARs from the system variable hash.
|
|
Filter for SESSION scope.
|
|
*/
|
|
bool PFS_system_variable_cache::do_initialize_session(void)
|
|
{
|
|
/* Block plugins from unloading. */
|
|
mysql_mutex_lock(&LOCK_plugin_delete);
|
|
|
|
/* Build the array. */
|
|
bool ret= init_show_var_array(OPT_SESSION, true);
|
|
|
|
mysql_mutex_unlock(&LOCK_plugin_delete);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
Match system variable scope to desired scope.
|
|
*/
|
|
bool PFS_system_variable_cache::match_scope(int scope)
|
|
{
|
|
switch (scope)
|
|
{
|
|
case sys_var::GLOBAL:
|
|
return m_query_scope == OPT_GLOBAL;
|
|
break;
|
|
|
|
case sys_var::SESSION:
|
|
return (m_query_scope == OPT_GLOBAL || m_query_scope == OPT_SESSION);
|
|
break;
|
|
|
|
case sys_var::ONLY_SESSION:
|
|
return m_query_scope == OPT_SESSION;
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
Build a GLOBAL system variable cache.
|
|
*/
|
|
int PFS_system_variable_cache::do_materialize_global(void)
|
|
{
|
|
/* Block system variable additions or deletions. */
|
|
mysql_mutex_lock(&LOCK_global_system_variables);
|
|
|
|
m_materialized= false;
|
|
|
|
/*
|
|
Build array of SHOW_VARs from system variable hash. Do this within
|
|
LOCK_plugin_delete to ensure that the hash table remains unchanged
|
|
during materialization.
|
|
*/
|
|
if (!m_external_init)
|
|
init_show_var_array(OPT_GLOBAL, true);
|
|
|
|
/* Resolve the value for each SHOW_VAR in the array, add to cache. */
|
|
for (SHOW_VAR *show_var= m_show_var_array.front();
|
|
show_var->value && (show_var != m_show_var_array.end()); show_var++)
|
|
{
|
|
const char* name= show_var->name;
|
|
sys_var *value= (sys_var *)show_var->value;
|
|
assert(value);
|
|
|
|
if ((m_query_scope == OPT_GLOBAL) &&
|
|
(!my_strcasecmp(system_charset_info, name, "sql_log_bin")))
|
|
{
|
|
/*
|
|
PLEASE READ:
|
|
http://dev.mysql.com/doc/relnotes/mysql/5.7/en/news-5-7-6.html
|
|
|
|
SQL_LOG_BIN is:
|
|
- declared in sys_vars.cc as both GLOBAL and SESSION in 5.7
|
|
- impossible to SET with SET GLOBAL (raises an error)
|
|
- and yet can be read with @@global.sql_log_bin
|
|
|
|
When show_compatibility_56 = ON,
|
|
- SHOW GLOBAL VARIABLES does expose a row for SQL_LOG_BIN
|
|
- INFORMATION_SCHEMA.GLOBAL_VARIABLES also does expose a row,
|
|
both are for backward compatibility of existing applications,
|
|
so that no application logic change is required.
|
|
|
|
Now, with show_compatibility_56 = OFF (aka, in this code)
|
|
- SHOW GLOBAL VARIABLES does -- not -- expose a row for SQL_LOG_BIN
|
|
- PERFORMANCE_SCHEMA.GLOBAL_VARIABLES also does -- not -- expose a row
|
|
so that a clean interface is exposed to (upgraded and modified) applications.
|
|
|
|
The assert below will fail once SQL_LOG_BIN really is defined
|
|
as SESSION_ONLY (in 5.8), so that this special case can be removed.
|
|
*/
|
|
assert(value->scope() == sys_var::SESSION);
|
|
continue;
|
|
}
|
|
|
|
/* Match the system variable scope to the target scope. */
|
|
if (match_scope(value->scope()))
|
|
{
|
|
/* Resolve value, convert to text, add to cache. */
|
|
System_variable system_var(m_current_thd, show_var, m_query_scope, false);
|
|
m_cache.push(system_var);
|
|
}
|
|
}
|
|
|
|
m_materialized= true;
|
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Build a GLOBAL and SESSION system variable cache.
|
|
*/
|
|
int PFS_system_variable_cache::do_materialize_all(THD *unsafe_thd)
|
|
{
|
|
int ret= 1;
|
|
|
|
m_unsafe_thd= unsafe_thd;
|
|
m_safe_thd= NULL;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Block plugins from unloading. */
|
|
mysql_mutex_lock(&LOCK_plugin_delete);
|
|
|
|
/*
|
|
Build array of SHOW_VARs from system variable hash. Do this within
|
|
LOCK_plugin_delete to ensure that the hash table remains unchanged
|
|
while this thread is materialized.
|
|
*/
|
|
if (!m_external_init)
|
|
init_show_var_array(OPT_SESSION, false);
|
|
|
|
/* Get and lock a validated THD from the thread manager. */
|
|
if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
|
|
{
|
|
DEBUG_SYNC(m_current_thd, "materialize_session_variable_array_THD_locked");
|
|
for (SHOW_VAR *show_var= m_show_var_array.front();
|
|
show_var->value && (show_var != m_show_var_array.end()); show_var++)
|
|
{
|
|
/* Resolve value, convert to text, add to cache. */
|
|
System_variable system_var(m_safe_thd, show_var, m_query_scope, false);
|
|
m_cache.push(system_var);
|
|
}
|
|
|
|
/* Release lock taken in get_THD(). */
|
|
mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
|
|
|
|
m_materialized= true;
|
|
ret= 0;
|
|
}
|
|
|
|
mysql_mutex_unlock(&LOCK_plugin_delete);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
Allocate and assign mem_root for system variable materialization.
|
|
*/
|
|
void PFS_system_variable_cache::set_mem_root(void)
|
|
{
|
|
if (m_mem_sysvar_ptr == NULL)
|
|
{
|
|
init_sql_alloc(PSI_INSTRUMENT_ME, &m_mem_sysvar, SYSVAR_MEMROOT_BLOCK_SIZE, 0, 0);
|
|
m_mem_sysvar_ptr= &m_mem_sysvar;
|
|
}
|
|
m_mem_thd= ¤t_thd->mem_root; /* pointer to current THD mem_root */
|
|
m_mem_thd_save= *m_mem_thd; /* restore later */
|
|
*m_mem_thd= &m_mem_sysvar; /* use temporary mem_root */
|
|
}
|
|
|
|
/**
|
|
Mark memory blocks in the temporary mem_root as free.
|
|
Restore THD::mem_root.
|
|
*/
|
|
void PFS_system_variable_cache::clear_mem_root(void)
|
|
{
|
|
if (m_mem_sysvar_ptr)
|
|
{
|
|
free_root(&m_mem_sysvar, MYF(MY_MARK_BLOCKS_FREE));
|
|
*m_mem_thd= m_mem_thd_save; /* restore original mem_root */
|
|
m_mem_thd= NULL;
|
|
m_mem_thd_save= NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Free the temporary mem_root.
|
|
Restore THD::mem_root if necessary.
|
|
*/
|
|
void PFS_system_variable_cache::free_mem_root(void)
|
|
{
|
|
if (m_mem_sysvar_ptr)
|
|
{
|
|
free_root(&m_mem_sysvar, MYF(0));
|
|
m_mem_sysvar_ptr= NULL;
|
|
if (m_mem_thd && m_mem_thd_save)
|
|
{
|
|
*m_mem_thd= m_mem_thd_save; /* restore original mem_root */
|
|
m_mem_thd= NULL;
|
|
m_mem_thd_save= NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Build a SESSION system variable cache for a pfs_thread.
|
|
Requires that init_show_var_array() has already been called.
|
|
Return 0 for success.
|
|
*/
|
|
int PFS_system_variable_cache::do_materialize_session(PFS_thread *pfs_thread)
|
|
{
|
|
int ret= 1;
|
|
|
|
m_pfs_thread= pfs_thread;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Block plugins from unloading. */
|
|
mysql_mutex_lock(&LOCK_plugin_delete);
|
|
|
|
/* The SHOW_VAR array must be initialized externally. */
|
|
assert(m_initialized);
|
|
|
|
/* Use a temporary mem_root to avoid depleting THD mem_root. */
|
|
if (m_use_mem_root)
|
|
set_mem_root();
|
|
|
|
/* Get and lock a validated THD from the thread manager. */
|
|
if ((m_safe_thd= get_THD(pfs_thread)) != NULL)
|
|
{
|
|
for (SHOW_VAR *show_var= m_show_var_array.front();
|
|
show_var->value && (show_var != m_show_var_array.end()); show_var++)
|
|
{
|
|
sys_var *value= (sys_var *)show_var->value;
|
|
|
|
/* Match the system variable scope to the target scope. */
|
|
if (match_scope(value->scope()))
|
|
{
|
|
/* Resolve value, convert to text, add to cache. */
|
|
System_variable system_var(m_safe_thd, show_var, m_query_scope, false);
|
|
m_cache.push(system_var);
|
|
}
|
|
}
|
|
|
|
/* Release lock taken in get_THD(). */
|
|
mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
|
|
|
|
m_materialized= true;
|
|
ret= 0;
|
|
}
|
|
|
|
/* Mark mem_root blocks as free. */
|
|
if (m_use_mem_root)
|
|
clear_mem_root();
|
|
|
|
mysql_mutex_unlock(&LOCK_plugin_delete);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
Materialize a single system variable for a pfs_thread.
|
|
Requires that init_show_var_array() has already been called.
|
|
Return 0 for success.
|
|
*/
|
|
int PFS_system_variable_cache::do_materialize_session(PFS_thread *pfs_thread, uint index)
|
|
{
|
|
int ret= 1;
|
|
|
|
m_pfs_thread= pfs_thread;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Block plugins from unloading. */
|
|
mysql_mutex_lock(&LOCK_plugin_delete);
|
|
|
|
/* The SHOW_VAR array must be initialized externally. */
|
|
assert(m_initialized);
|
|
|
|
/* Get and lock a validated THD from the thread manager. */
|
|
if ((m_safe_thd= get_THD(pfs_thread)) != NULL)
|
|
{
|
|
SHOW_VAR *show_var= &m_show_var_array.at(index);
|
|
|
|
if (show_var && show_var->value &&
|
|
(show_var != m_show_var_array.end()))
|
|
{
|
|
sys_var *value= (sys_var *)show_var->value;
|
|
|
|
/* Match the system variable scope to the target scope. */
|
|
if (match_scope(value->scope()))
|
|
{
|
|
/* Resolve value, convert to text, add to cache. */
|
|
System_variable system_var(m_safe_thd, show_var, m_query_scope, false);
|
|
m_cache.push(system_var);
|
|
}
|
|
}
|
|
|
|
/* Release lock taken in get_THD(). */
|
|
mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
|
|
|
|
m_materialized= true;
|
|
ret= 0;
|
|
}
|
|
|
|
mysql_mutex_unlock(&LOCK_plugin_delete);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
Build a SESSION system variable cache for a THD.
|
|
*/
|
|
int PFS_system_variable_cache::do_materialize_session(THD *unsafe_thd)
|
|
{
|
|
int ret= 1;
|
|
|
|
m_unsafe_thd= unsafe_thd;
|
|
m_safe_thd= NULL;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Block plugins from unloading. */
|
|
mysql_mutex_lock(&LOCK_plugin_delete);
|
|
|
|
/*
|
|
Build array of SHOW_VARs from system variable hash. Do this within
|
|
LOCK_plugin_delete to ensure that the hash table remains unchanged
|
|
while this thread is materialized.
|
|
*/
|
|
if (!m_external_init)
|
|
init_show_var_array(OPT_SESSION, true);
|
|
|
|
/* Get and lock a validated THD from the thread manager. */
|
|
if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
|
|
{
|
|
for (SHOW_VAR *show_var= m_show_var_array.front();
|
|
show_var->value && (show_var != m_show_var_array.end()); show_var++)
|
|
{
|
|
sys_var *value = (sys_var *)show_var->value;
|
|
|
|
/* Match the system variable scope to the target scope. */
|
|
if (match_scope(value->scope()))
|
|
{
|
|
/* Resolve value, convert to text, add to cache. */
|
|
System_variable system_var(m_safe_thd, show_var, m_query_scope, false);
|
|
m_cache.push(system_var);
|
|
}
|
|
}
|
|
|
|
/* Release lock taken in get_THD(). */
|
|
mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
|
|
|
|
m_materialized= true;
|
|
ret= 0;
|
|
}
|
|
|
|
mysql_mutex_unlock(&LOCK_plugin_delete);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/**
|
|
CLASS System_variable
|
|
*/
|
|
|
|
/**
|
|
Empty placeholder.
|
|
*/
|
|
System_variable::System_variable()
|
|
: m_name(NULL), m_name_length(0), m_value_length(0), m_type(SHOW_UNDEF), m_scope(0),
|
|
m_ignore(false), m_charset(NULL), m_initialized(false)
|
|
{
|
|
m_value_str[0]= '\0';
|
|
}
|
|
|
|
/**
|
|
GLOBAL or SESSION system variable.
|
|
*/
|
|
System_variable::System_variable(THD *target_thd, const SHOW_VAR *show_var,
|
|
enum_var_type query_scope, bool ignore)
|
|
: m_name(NULL), m_name_length(0), m_value_length(0), m_type(SHOW_UNDEF), m_scope(0),
|
|
m_ignore(ignore), m_charset(NULL), m_initialized(false)
|
|
{
|
|
init(target_thd, show_var, query_scope);
|
|
}
|
|
|
|
/**
|
|
Get sys_var value from global or local source then convert to string.
|
|
*/
|
|
void System_variable::init(THD *target_thd, const SHOW_VAR *show_var,
|
|
enum_var_type query_scope)
|
|
{
|
|
if (show_var == NULL || show_var->name == NULL)
|
|
return;
|
|
|
|
DBUG_ASSERT(show_var->type == SHOW_SYS);
|
|
|
|
m_name= show_var->name;
|
|
m_name_length= strlen(m_name);
|
|
|
|
/* Deprecated variables are ignored but must still be accounted for. */
|
|
if (m_ignore)
|
|
{
|
|
m_value_str[0]= '\0';
|
|
m_value_length= 0;
|
|
m_initialized= true;
|
|
return;
|
|
}
|
|
|
|
/* Block remote target thread from updating this system variable. */
|
|
/*XXX
|
|
THD *current_thread= current_thd;
|
|
if (target_thd != current_thread)
|
|
mysql_mutex_lock(&target_thd->LOCK_thd_sysvar);*/
|
|
|
|
sys_var *system_var= (sys_var *)show_var->value;
|
|
assert(system_var != NULL);
|
|
m_charset= system_var->charset(target_thd);
|
|
m_type= system_var->show_type();
|
|
m_scope= system_var->scope();
|
|
|
|
/* Get the value of the system variable. */
|
|
String buf(m_value_str, sizeof(m_value_str) - 1, system_charset_info);
|
|
if (!system_var->val_str_nolock(&buf, target_thd,
|
|
system_var->value_ptr(target_thd, query_scope, &null_clex_str)))
|
|
buf.length(0);
|
|
|
|
m_value_length= MY_MIN(buf.length(), SHOW_VAR_FUNC_BUFF_SIZE);
|
|
|
|
/* Returned value may reference a string other than m_value_str. */
|
|
if (buf.ptr() != m_value_str)
|
|
memcpy(m_value_str, buf.ptr(), m_value_length);
|
|
m_value_str[m_value_length]= 0;
|
|
|
|
/*XXX
|
|
if (target_thd != current_thread)
|
|
mysql_mutex_unlock(&target_thd->LOCK_thd_sysvar);*/
|
|
|
|
m_initialized= true;
|
|
}
|
|
|
|
|
|
/**
|
|
CLASS PFS_status_variable_cache
|
|
*/
|
|
|
|
PFS_status_variable_cache::
|
|
PFS_status_variable_cache(bool external_init) :
|
|
PFS_variable_cache<Status_variable>(external_init),
|
|
m_show_command(false), m_sum_client_status(NULL)
|
|
{
|
|
/* Determine if the originating query is a SHOW command. */
|
|
m_show_command= (m_current_thd->lex->sql_command == SQLCOM_SHOW_STATUS);
|
|
}
|
|
|
|
/**
|
|
Build cache of SESSION status variables for a user.
|
|
*/
|
|
int PFS_status_variable_cache::materialize_user(PFS_user *pfs_user)
|
|
{
|
|
if (!pfs_user)
|
|
return 1;
|
|
|
|
if (is_materialized(pfs_user))
|
|
return 0;
|
|
|
|
if (!pfs_user->m_lock.is_populated())
|
|
return 1;
|
|
|
|
/* Set callback function. */
|
|
m_sum_client_status= sum_user_status;
|
|
return do_materialize_client((PFS_client *)pfs_user);
|
|
}
|
|
|
|
/**
|
|
Build cache of SESSION status variables for a host.
|
|
*/
|
|
int PFS_status_variable_cache::materialize_host(PFS_host *pfs_host)
|
|
{
|
|
if (!pfs_host)
|
|
return 1;
|
|
|
|
if (is_materialized(pfs_host))
|
|
return 0;
|
|
|
|
if (!pfs_host->m_lock.is_populated())
|
|
return 1;
|
|
|
|
/* Set callback function. */
|
|
m_sum_client_status= sum_host_status;
|
|
return do_materialize_client((PFS_client *)pfs_host);
|
|
}
|
|
|
|
/**
|
|
Build cache of SESSION status variables for an account.
|
|
*/
|
|
int PFS_status_variable_cache::materialize_account(PFS_account *pfs_account)
|
|
{
|
|
if (!pfs_account)
|
|
return 1;
|
|
|
|
if (is_materialized(pfs_account))
|
|
return 0;
|
|
|
|
if (!pfs_account->m_lock.is_populated())
|
|
return 1;
|
|
|
|
/* Set callback function. */
|
|
m_sum_client_status= sum_account_status;
|
|
return do_materialize_client((PFS_client *)pfs_account);
|
|
}
|
|
/**
|
|
Compare status variable scope to desired scope.
|
|
@param variable_scope Scope of current status variable
|
|
@return TRUE if variable matches the query scope
|
|
*/
|
|
bool PFS_status_variable_cache::match_scope(SHOW_SCOPE variable_scope, bool strict)
|
|
{
|
|
switch (variable_scope)
|
|
{
|
|
case SHOW_SCOPE_GLOBAL:
|
|
return (m_query_scope == OPT_GLOBAL) || (! strict && (m_query_scope == OPT_SESSION));
|
|
break;
|
|
case SHOW_SCOPE_SESSION:
|
|
/* Ignore session-only vars if aggregating by user, host or account. */
|
|
if (m_aggregate)
|
|
return false;
|
|
else
|
|
return (m_query_scope == OPT_SESSION);
|
|
break;
|
|
case SHOW_SCOPE_ALL:
|
|
return (m_query_scope == OPT_GLOBAL || m_query_scope == OPT_SESSION);
|
|
break;
|
|
case SHOW_SCOPE_UNDEF:
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
Exclude specific status variables from the query by name or prefix.
|
|
Return TRUE if variable should be filtered.
|
|
*/
|
|
bool PFS_status_variable_cache::filter_by_name(const SHOW_VAR *show_var)
|
|
{
|
|
assert(show_var);
|
|
assert(show_var->name);
|
|
|
|
if (show_var->type == SHOW_ARRAY)
|
|
{
|
|
/* The SHOW_ARRAY name is the prefix for the variables in the subarray. */
|
|
const char *prefix= show_var->name;
|
|
/* Exclude COM counters if not a SHOW STATUS command. */
|
|
if (!my_strcasecmp(system_charset_info, prefix, "Com") && !m_show_command)
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Slave status resides in Performance Schema replication tables. Exclude
|
|
these slave status variables from the SHOW STATUS command and from the
|
|
status tables.
|
|
Assume null prefix to ensure that only server-defined slave status
|
|
variables are filtered.
|
|
*/
|
|
const char *name= show_var->name;
|
|
if (!my_strcasecmp(system_charset_info, name, "Slave_running") ||
|
|
!my_strcasecmp(system_charset_info, name, "Slave_retried_transactions") ||
|
|
!my_strcasecmp(system_charset_info, name, "Slave_last_heartbeat") ||
|
|
!my_strcasecmp(system_charset_info, name, "Slave_received_heartbeats") ||
|
|
!my_strcasecmp(system_charset_info, name, "Slave_heartbeat_period"))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
Check that the variable type is aggregatable.
|
|
|
|
@param variable_type Status variable type
|
|
@return TRUE if variable type can be aggregated
|
|
*/
|
|
bool PFS_status_variable_cache::can_aggregate(enum_mysql_show_type variable_type)
|
|
{
|
|
switch(variable_type)
|
|
{
|
|
/*
|
|
All server status counters that are totaled across threads are defined in
|
|
system_status_var as either SHOW_LONGLONG_STATUS or SHOW_LONG_STATUS.
|
|
These data types are not available to plugins.
|
|
*/
|
|
case SHOW_LONGLONG_STATUS:
|
|
case SHOW_LONG_STATUS:
|
|
return true;
|
|
break;
|
|
|
|
/* Server and plugin */
|
|
case SHOW_UNDEF:
|
|
case SHOW_BOOL:
|
|
case SHOW_CHAR:
|
|
case SHOW_CHAR_PTR:
|
|
case SHOW_ARRAY:
|
|
case SHOW_FUNC:
|
|
case SHOW_INT:
|
|
case SHOW_LONG:
|
|
case SHOW_LONGLONG:
|
|
case SHOW_DOUBLE:
|
|
/* Server only */
|
|
case SHOW_HAVE:
|
|
case SHOW_MY_BOOL:
|
|
case SHOW_SYS:
|
|
case SHOW_LEX_STRING:
|
|
case SHOW_KEY_CACHE_LONG:
|
|
case SHOW_DOUBLE_STATUS:
|
|
case SHOW_HA_ROWS:
|
|
case SHOW_LONG_NOFLUSH:
|
|
case SHOW_SLONG:
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if a status variable should be excluded from the query.
|
|
Return TRUE if the variable should be excluded.
|
|
*/
|
|
bool PFS_status_variable_cache::filter_show_var(const SHOW_VAR *show_var, bool strict)
|
|
{
|
|
/* Match the variable scope with the query scope. */
|
|
if (!match_scope(show_scope_from_type(show_var->type), strict))
|
|
return true;
|
|
|
|
/* Exclude specific status variables by name or prefix. */
|
|
if (filter_by_name(show_var))
|
|
return true;
|
|
|
|
/* For user, host or account, ignore variables having non-aggregatable types. */
|
|
if (m_aggregate && !can_aggregate(show_var->type))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
Build an array of SHOW_VARs from the global status array. Expand nested
|
|
subarrays, filter unwanted variables.
|
|
NOTE: Must be done inside of LOCK_status to guard against plugin load/unload.
|
|
*/
|
|
bool PFS_status_variable_cache::init_show_var_array(enum_var_type scope, bool strict)
|
|
{
|
|
assert(!m_initialized);
|
|
|
|
/* Resize if necessary. */
|
|
m_show_var_array.reserve(all_status_vars.elements + 1);
|
|
|
|
m_query_scope= scope;
|
|
|
|
for (SHOW_VAR *show_var_iter= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
|
|
show_var_iter != dynamic_element(&all_status_vars, all_status_vars.elements, SHOW_VAR *);
|
|
show_var_iter++)
|
|
{
|
|
SHOW_VAR show_var= *show_var_iter;
|
|
|
|
/* Check if this status var should be excluded from the query. */
|
|
if (filter_show_var(&show_var, strict))
|
|
continue;
|
|
|
|
if (show_var.type == SHOW_ARRAY)
|
|
{
|
|
/* Expand nested subarray. The name is used as a prefix. */
|
|
expand_show_var_array((SHOW_VAR *)show_var.value, show_var.name, strict);
|
|
}
|
|
else
|
|
{
|
|
show_var.name= make_show_var_name(NULL, show_var.name);
|
|
m_show_var_array.push(show_var);
|
|
}
|
|
}
|
|
|
|
/* Last element is NULL. */
|
|
st_mysql_show_var empty= {0,0,SHOW_UNDEF};
|
|
m_show_var_array.push(empty);
|
|
|
|
/* Get the latest version of all_status_vars. */
|
|
m_version= get_status_vars_version();
|
|
|
|
/* Increase cache size if necessary. */
|
|
m_cache.reserve(m_show_var_array.elements());
|
|
|
|
m_initialized= true;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
Expand a nested subarray of status variables, indicated by a type of SHOW_ARRAY.
|
|
*/
|
|
void PFS_status_variable_cache::expand_show_var_array(const SHOW_VAR *show_var_array, const char *prefix, bool strict)
|
|
{
|
|
for (const SHOW_VAR *show_var_ptr= show_var_array;
|
|
show_var_ptr && show_var_ptr->name;
|
|
show_var_ptr++)
|
|
{
|
|
SHOW_VAR show_var= *show_var_ptr;
|
|
|
|
if (filter_show_var(&show_var, strict))
|
|
continue;
|
|
|
|
if (show_var.type == SHOW_ARRAY)
|
|
{
|
|
char name_buf[SHOW_VAR_MAX_NAME_LEN];
|
|
show_var.name= make_show_var_name(prefix, show_var.name, name_buf, sizeof(name_buf));
|
|
/* Expand nested subarray. The name is used as a prefix. */
|
|
expand_show_var_array((SHOW_VAR *)show_var.value, show_var.name, strict);
|
|
}
|
|
else
|
|
{
|
|
/* Add the SHOW_VAR element. Make a local copy of the name string. */
|
|
show_var.name= make_show_var_name(prefix, show_var.name);
|
|
m_show_var_array.push(show_var);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Build the complete status variable name, with prefix. Return in buffer provided.
|
|
*/
|
|
char * PFS_status_variable_cache::make_show_var_name(const char* prefix, const char* name,
|
|
char *name_buf, size_t buf_len)
|
|
{
|
|
assert(name_buf != NULL);
|
|
char *prefix_end= name_buf;
|
|
|
|
if (prefix && *prefix)
|
|
{
|
|
/* Drop the prefix into the front of the name buffer. */
|
|
prefix_end= my_stpnmov(name_buf, prefix, buf_len-1);
|
|
*prefix_end++= '_';
|
|
}
|
|
|
|
/* Restrict name length to remaining buffer size. */
|
|
size_t max_name_len= name_buf + buf_len - prefix_end;
|
|
|
|
/* Load the name into the buffer after the prefix. */
|
|
my_stpnmov(prefix_end, name, max_name_len);
|
|
name_buf[buf_len-1]= 0;
|
|
|
|
return (name_buf);
|
|
}
|
|
|
|
/**
|
|
Make a copy of the name string prefixed with the subarray name if necessary.
|
|
*/
|
|
char * PFS_status_variable_cache::make_show_var_name(const char* prefix, const char* name)
|
|
{
|
|
char name_buf[SHOW_VAR_MAX_NAME_LEN];
|
|
size_t buf_len= sizeof(name_buf);
|
|
make_show_var_name(prefix, name, name_buf, buf_len);
|
|
return m_current_thd->strdup(name_buf); /* freed at statement end */
|
|
}
|
|
|
|
/**
|
|
Build an internal SHOW_VAR array from the external status variable array.
|
|
*/
|
|
bool PFS_status_variable_cache::do_initialize_session(void)
|
|
{
|
|
/* Acquire LOCK_status to guard against plugin load/unload. */
|
|
//if (m_current_thd->fill_status_recursion_level++ == 0)
|
|
mysql_mutex_lock(&LOCK_status);
|
|
|
|
bool ret= init_show_var_array(OPT_SESSION, true);
|
|
|
|
//if (m_current_thd->fill_status_recursion_level-- == 1)
|
|
mysql_mutex_unlock(&LOCK_status);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
For the current THD, use initial_status_vars taken from before the query start.
|
|
*/
|
|
STATUS_VAR *PFS_status_variable_cache::set_status_vars(void)
|
|
{
|
|
STATUS_VAR *status_vars;
|
|
if (m_safe_thd == m_current_thd && m_current_thd->initial_status_var != NULL)
|
|
status_vars= m_current_thd->initial_status_var;
|
|
else
|
|
status_vars= &m_safe_thd->status_var;
|
|
|
|
return status_vars;
|
|
}
|
|
|
|
/**
|
|
Build cache for GLOBAL status variables using values totaled from all threads.
|
|
*/
|
|
int PFS_status_variable_cache::do_materialize_global(void)
|
|
{
|
|
STATUS_VAR status_totals;
|
|
|
|
m_materialized= false;
|
|
DEBUG_SYNC(m_current_thd, "before_materialize_global_status_array");
|
|
|
|
/* Acquire LOCK_status to guard against plugin load/unload. */
|
|
//if (m_current_thd->fill_status_recursion_level++ == 0)
|
|
mysql_mutex_lock(&LOCK_status);
|
|
|
|
/*
|
|
Build array of SHOW_VARs from global status array. Do this within
|
|
LOCK_status to ensure that the array remains unchanged during
|
|
materialization.
|
|
*/
|
|
if (!m_external_init)
|
|
init_show_var_array(OPT_GLOBAL, true);
|
|
|
|
/*
|
|
Collect totals for all active threads. Start with global status vars as a
|
|
baseline.
|
|
*/
|
|
PFS_connection_status_visitor visitor(&status_totals);
|
|
PFS_connection_iterator::visit_global(false, /* hosts */
|
|
false, /* users */
|
|
false, /* accounts */
|
|
false, /* threads */
|
|
true, /* THDs */
|
|
&visitor);
|
|
/*
|
|
Build the status variable cache using the SHOW_VAR array as a reference.
|
|
Use the status totals collected from all threads.
|
|
*/
|
|
manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true);
|
|
|
|
//if (m_current_thd->fill_status_recursion_level-- == 1)
|
|
mysql_mutex_unlock(&LOCK_status);
|
|
|
|
m_materialized= true;
|
|
DEBUG_SYNC(m_current_thd, "after_materialize_global_status_array");
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Build GLOBAL and SESSION status variable cache using values for a non-instrumented thread.
|
|
*/
|
|
int PFS_status_variable_cache::do_materialize_all(THD* unsafe_thd)
|
|
{
|
|
int ret= 1;
|
|
assert(unsafe_thd != NULL);
|
|
|
|
m_unsafe_thd= unsafe_thd;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Avoid recursive acquisition of LOCK_status. */
|
|
//if (m_current_thd->fill_status_recursion_level++ == 0)
|
|
mysql_mutex_lock(&LOCK_status);
|
|
|
|
/*
|
|
Build array of SHOW_VARs from global status array. Do this within
|
|
LOCK_status to ensure that the array remains unchanged while this
|
|
thread is materialized.
|
|
*/
|
|
if (!m_external_init)
|
|
init_show_var_array(OPT_SESSION, false);
|
|
|
|
/* Get and lock a validated THD from the thread manager. */
|
|
if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
|
|
{
|
|
/*
|
|
Build the status variable cache using the SHOW_VAR array as a reference.
|
|
Use the status values from the THD protected by the thread manager lock.
|
|
*/
|
|
STATUS_VAR *status_vars= set_status_vars();
|
|
manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, false);
|
|
|
|
/* Release lock taken in get_THD(). */
|
|
mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
|
|
|
|
m_materialized= true;
|
|
ret= 0;
|
|
}
|
|
|
|
//if (m_current_thd->fill_status_recursion_level-- == 1)
|
|
mysql_mutex_unlock(&LOCK_status);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
Build SESSION status variable cache using values for a non-instrumented thread.
|
|
*/
|
|
int PFS_status_variable_cache::do_materialize_session(THD* unsafe_thd)
|
|
{
|
|
int ret= 1;
|
|
assert(unsafe_thd != NULL);
|
|
|
|
m_unsafe_thd= unsafe_thd;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Avoid recursive acquisition of LOCK_status. */
|
|
//if (m_current_thd->fill_status_recursion_level++ == 0)
|
|
mysql_mutex_lock(&LOCK_status);
|
|
|
|
/*
|
|
Build array of SHOW_VARs from global status array. Do this within
|
|
LOCK_status to ensure that the array remains unchanged while this
|
|
thread is materialized.
|
|
*/
|
|
if (!m_external_init)
|
|
init_show_var_array(OPT_SESSION, true);
|
|
|
|
/* Get and lock a validated THD from the thread manager. */
|
|
if ((m_safe_thd= get_THD(unsafe_thd)) != NULL)
|
|
{
|
|
/*
|
|
Build the status variable cache using the SHOW_VAR array as a reference.
|
|
Use the status values from the THD protected by the thread manager lock.
|
|
*/
|
|
STATUS_VAR *status_vars= set_status_vars();
|
|
manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, true);
|
|
|
|
/* Release lock taken in get_THD(). */
|
|
mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
|
|
|
|
m_materialized= true;
|
|
ret= 0;
|
|
}
|
|
|
|
//if (m_current_thd->fill_status_recursion_level-- == 1)
|
|
mysql_mutex_unlock(&LOCK_status);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
Build SESSION status variable cache using values for a PFS_thread.
|
|
NOTE: Requires that init_show_var_array() has already been called.
|
|
*/
|
|
int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread)
|
|
{
|
|
int ret= 1;
|
|
assert(pfs_thread != NULL);
|
|
|
|
m_pfs_thread= pfs_thread;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Acquire LOCK_status to guard against plugin load/unload. */
|
|
//if (m_current_thd->fill_status_recursion_level++ == 0)
|
|
mysql_mutex_lock(&LOCK_status);
|
|
|
|
/* The SHOW_VAR array must be initialized externally. */
|
|
assert(m_initialized);
|
|
|
|
/* Get and lock a validated THD from the thread manager. */
|
|
if ((m_safe_thd= get_THD(pfs_thread)) != NULL)
|
|
{
|
|
/*
|
|
Build the status variable cache using the SHOW_VAR array as a reference.
|
|
Use the status values from the THD protected by the thread manager lock.
|
|
*/
|
|
STATUS_VAR *status_vars= set_status_vars();
|
|
manifest(m_safe_thd, m_show_var_array.front(), status_vars, "", false, true);
|
|
|
|
/* Release lock taken in get_THD(). */
|
|
mysql_mutex_unlock(&m_safe_thd->LOCK_thd_data);
|
|
|
|
m_materialized= true;
|
|
ret= 0;
|
|
}
|
|
|
|
//if (m_current_thd->fill_status_recursion_level-- == 1)
|
|
mysql_mutex_unlock(&LOCK_status);
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
Build cache of SESSION status variables using the status values provided.
|
|
The cache is associated with a user, host or account, but not with any
|
|
particular thread.
|
|
NOTE: Requires that init_show_var_array() has already been called.
|
|
*/
|
|
int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client)
|
|
{
|
|
assert(pfs_client != NULL);
|
|
STATUS_VAR status_totals;
|
|
|
|
m_pfs_client= pfs_client;
|
|
m_materialized= false;
|
|
m_cache.clear();
|
|
|
|
/* Acquire LOCK_status to guard against plugin load/unload. */
|
|
//if (m_current_thd->fill_status_recursion_level++ == 0)
|
|
mysql_mutex_lock(&LOCK_status);
|
|
|
|
/* The SHOW_VAR array must be initialized externally. */
|
|
assert(m_initialized);
|
|
|
|
/*
|
|
Generate status totals from active threads and from totals aggregated
|
|
from disconnected threads.
|
|
*/
|
|
m_sum_client_status(pfs_client, &status_totals);
|
|
|
|
/*
|
|
Build the status variable cache using the SHOW_VAR array as a reference and
|
|
the status totals collected from threads associated with this client.
|
|
*/
|
|
manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true);
|
|
|
|
//if (m_current_thd->fill_status_recursion_level-- == 1)
|
|
mysql_mutex_unlock(&LOCK_status);
|
|
|
|
m_materialized= true;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
Build the status variable cache from the expanded and sorted SHOW_VAR array.
|
|
Resolve status values using the STATUS_VAR struct provided.
|
|
*/
|
|
void PFS_status_variable_cache::manifest(THD *thd, const SHOW_VAR *show_var_array,
|
|
STATUS_VAR *status_vars, const char *prefix,
|
|
bool nested_array, bool strict)
|
|
{
|
|
for (const SHOW_VAR *show_var_iter= show_var_array;
|
|
show_var_iter && show_var_iter->name;
|
|
show_var_iter++)
|
|
{
|
|
// work buffer, must be aligned to handle long/longlong values
|
|
my_aligned_storage<SHOW_VAR_FUNC_BUFF_SIZE+1, MY_ALIGNOF(longlong)>
|
|
value_buf;
|
|
SHOW_VAR show_var_tmp;
|
|
const SHOW_VAR *show_var_ptr= show_var_iter; /* preserve array pointer */
|
|
|
|
/*
|
|
If the value is a function reference, then execute the function and
|
|
reevaluate the new SHOW_TYPE and value. Handle nested case where
|
|
SHOW_FUNC resolves to another SHOW_FUNC.
|
|
*/
|
|
if (show_var_ptr->type == SHOW_FUNC)
|
|
{
|
|
show_var_tmp= *show_var_ptr;
|
|
/*
|
|
Execute the function reference in show_var_tmp->value, which returns
|
|
show_var_tmp with a new type and new value.
|
|
*/
|
|
for (const SHOW_VAR *var= show_var_ptr; var->type == SHOW_FUNC; var= &show_var_tmp)
|
|
{
|
|
((mysql_show_var_func)(var->value))(thd, &show_var_tmp, value_buf.data, NULL, m_query_scope);
|
|
}
|
|
show_var_ptr= &show_var_tmp;
|
|
}
|
|
|
|
/*
|
|
If we are expanding a SHOW_ARRAY, filter variables that were not prefiltered by
|
|
init_show_var_array().
|
|
*/
|
|
if (nested_array && filter_show_var(show_var_ptr, strict))
|
|
continue;
|
|
|
|
if (show_var_ptr->type == SHOW_ARRAY)
|
|
{
|
|
/*
|
|
Status variables of type SHOW_ARRAY were expanded and filtered by
|
|
init_show_var_array(), except where a SHOW_FUNC resolves into a
|
|
SHOW_ARRAY, such as with InnoDB. Recurse to expand the subarray.
|
|
*/
|
|
manifest(thd, (SHOW_VAR *)show_var_ptr->value, status_vars, show_var_ptr->name, true, strict);
|
|
}
|
|
else
|
|
{
|
|
/* Add the materialized status variable to the cache. */
|
|
SHOW_VAR show_var= *show_var_ptr;
|
|
/*
|
|
For nested array expansions, make a copy of the variable name, just as
|
|
done in init_show_var_array().
|
|
*/
|
|
if (nested_array)
|
|
show_var.name= make_show_var_name(prefix, show_var_ptr->name);
|
|
|
|
/* Convert status value to string format. Add to the cache. */
|
|
Status_variable status_var(&show_var, status_vars, m_query_scope);
|
|
m_cache.push(status_var);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
CLASS Status_variable
|
|
*/
|
|
Status_variable::Status_variable(const SHOW_VAR *show_var, STATUS_VAR *status_vars, enum_var_type query_scope)
|
|
: m_name_length(0), m_value_length(0), m_type(SHOW_UNDEF),
|
|
m_charset(NULL), m_initialized(false)
|
|
{
|
|
init(show_var, status_vars, query_scope);
|
|
}
|
|
|
|
/**
|
|
Resolve status value, convert to string.
|
|
show_var->value is an offset into status_vars.
|
|
NOTE: Assumes LOCK_status is held.
|
|
*/
|
|
void Status_variable::init(const SHOW_VAR *show_var, STATUS_VAR *status_vars, enum_var_type query_scope)
|
|
{
|
|
if (show_var == NULL || show_var->name == NULL)
|
|
return;
|
|
m_name= show_var->name;
|
|
m_name_length= strlen(m_name);
|
|
m_type= show_var->type;
|
|
|
|
/* Get the value of the status variable. */
|
|
const char *value;
|
|
value= get_one_variable(current_thd, show_var, query_scope, m_type,
|
|
status_vars, &m_charset, m_value_str, &m_value_length);
|
|
m_value_length= MY_MIN(m_value_length, SHOW_VAR_FUNC_BUFF_SIZE);
|
|
m_charset= system_charset_info;
|
|
|
|
/* Returned value may reference a string other than m_value_str. */
|
|
if (value != m_value_str)
|
|
memcpy(m_value_str, value, m_value_length);
|
|
m_value_str[m_value_length]= 0;
|
|
|
|
m_initialized= true;
|
|
}
|
|
|
|
/*
|
|
Get status totals for this user from active THDs and related accounts.
|
|
*/
|
|
void sum_user_status(PFS_client *pfs_user, STATUS_VAR *status_totals)
|
|
{
|
|
PFS_connection_status_visitor visitor(status_totals);
|
|
PFS_connection_iterator::visit_user((PFS_user *)pfs_user,
|
|
true, /* accounts */
|
|
false, /* threads */
|
|
true, /* THDs */
|
|
&visitor);
|
|
}
|
|
|
|
/*
|
|
Get status totals for this host from active THDs and related accounts.
|
|
*/
|
|
void sum_host_status(PFS_client *pfs_host, STATUS_VAR *status_totals)
|
|
{
|
|
PFS_connection_status_visitor visitor(status_totals);
|
|
PFS_connection_iterator::visit_host((PFS_host *)pfs_host,
|
|
true, /* accounts */
|
|
false, /* threads */
|
|
true, /* THDs */
|
|
&visitor);
|
|
}
|
|
|
|
/*
|
|
Get status totals for this account from active THDs and from totals aggregated
|
|
from disconnectd threads.
|
|
*/
|
|
void sum_account_status(PFS_client *pfs_account, STATUS_VAR *status_totals)
|
|
{
|
|
PFS_connection_status_visitor visitor(status_totals);
|
|
PFS_connection_iterator::visit_account((PFS_account *)pfs_account,
|
|
false, /* threads */
|
|
true, /* THDs */
|
|
&visitor);
|
|
}
|
|
|
|
/**
|
|
Reset aggregated status counter stats for account, user and host.
|
|
NOTE: Assumes LOCK_status is held.
|
|
*/
|
|
void reset_pfs_status_stats()
|
|
{
|
|
reset_status_by_account();
|
|
reset_status_by_user();
|
|
reset_status_by_host();
|
|
}
|
|
|
|
/** @} */
|