Commit 031ee043 authored by unknown's avatar unknown

WL#2935 - SHOW STATUS support in plugins

The patch adds DYNAMIC_ARRAY all_status_vars, which is now the
sole source of status information for SHOW STATUS.  Status
variables can be added to and removed from the array dynamically.
SHOW STATUS command uses this array instead of static array
from mysqld.cc
Compatibility with the old, global list of status variables is
preserved in init_server_components(), where this global list is
simply appended to all_status_vars.


include/plugin.h:
  WL#2935 - SHOW STATUS support in plugins
plugin/fulltext/plugin_example.c:
  WL#2935 - SHOW STATUS support in plugins
  example
sql/ha_innodb.cc:
  s/struct show_var_st/SHOW_VAR/
sql/ha_innodb.h:
  s/struct show_var_st/SHOW_VAR/
sql/mysql_priv.h:
  WL#2935 - SHOW STATUS support in plugins
  add_status_vars(), remove_status_vars()
sql/mysqld.cc:
  bug: plugin_free must be called even with --skip-grants
  add_status_vars()/free_status_vars(), remove unused SHOW_xxx_CONST
  s/struct show_var_st/SHOW_VAR/
sql/set_var.cc:
  s/struct show_var_st/SHOW_VAR/
sql/sql_parse.cc:
  s/struct show_var_st/SHOW_VAR/
sql/sql_plugin.cc:
  WL#2935 - SHOW STATUS support in plugins
sql/sql_plugin.h:
  WL#2935 - SHOW STATUS support in plugins
sql/sql_show.cc:
  WL#2935 - SHOW STATUS support in plugins
  DYNAMIC_ARRAY all_status_vars, add_status_vars(), remove_status_vars()
  s/struct show_var_st/SHOW_VAR/
sql/structs.h:
  WL#2935 - SHOW STATUS support in plugins
  SHOW STATUS definitions moved to include/plugin.h and sql_plugin.h
  s/struct show_var_st/SHOW_VAR/
parent 88469c80
......@@ -41,7 +41,26 @@
int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0}}
#define mysql_declare_plugin_end ,{0,0,0,0,0,0,0,0}}
/*
declarations for SHOW STATUS support in plugins
*/
enum enum_mysql_show_type
{
SHOW_UNDEF, SHOW_BOOL, SHOW_MY_BOOL, SHOW_INT, SHOW_LONG,
SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
SHOW_ARRAY, SHOW_FUNC
};
struct st_mysql_show_var {
const char *name;
char *value;
enum enum_mysql_show_type type;
};
#define SHOW_VAR_FUNC_BUFF_SIZE 1024
typedef int (*mysql_show_var_func)(void *, struct st_mysql_show_var*, char *);
/*
Plugin description structure.
......@@ -57,6 +76,7 @@ struct st_mysql_plugin
int (*init)(void); /* the function to invoke when plugin is loaded */
int (*deinit)(void); /* the function to invoke when plugin is unloaded */
uint version; /* plugin version (for SHOW PLUGINS) */
struct st_mysql_show_var *status_vars;
};
/*************************************************************************
......
......@@ -18,6 +18,8 @@
#include <m_ctype.h>
#include <plugin.h>
long number_of_calls= 0; /* for SHOW STATUS, see below */
/*
Simple full-text parser plugin that acts as a replacement for the
built-in full-text parser:
......@@ -167,6 +169,8 @@ int simple_parser_parse(MYSQL_FTPARSER_PARAM *param)
{
char *end, *start, *docend= param->doc + param->length;
number_of_calls++;
for (end= start= param->doc;; end++)
{
if (end == docend)
......@@ -198,6 +202,16 @@ static struct st_mysql_ftparser simple_parser_descriptor=
simple_parser_deinit /* parser deinit function */
};
/*
Plugin status variables for SHOW STATUS
*/
struct st_mysql_show_var simple_status[]=
{
{"static", "just a static text", SHOW_CHAR},
{"called", (char *)&number_of_calls, SHOW_LONG},
{0,0,0}
};
/*
Plugin library descriptor
......@@ -211,6 +225,8 @@ mysql_declare_plugin
"MySQL AB", /* author */
"Simple Full-Text Parser", /* description */
simple_parser_plugin_init, /* init function (when loaded) */
simple_parser_plugin_deinit /* deinit function (when unloaded) */
simple_parser_plugin_deinit,/* deinit function (when unloaded) */
0x0001, /* version */
&simple_status /* status variables */
}
mysql_declare_plugin_end;
......@@ -253,7 +253,7 @@ innobase_commit_low(
/*================*/
trx_t* trx); /* in: transaction handle */
struct show_var_st innodb_status_variables[]= {
SHOW_VAR innodb_status_variables[]= {
{"buffer_pool_pages_data",
(char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
{"buffer_pool_pages_dirty",
......
......@@ -212,7 +212,7 @@ class ha_innobase: public handler
uint table_changes);
};
extern struct show_var_st innodb_status_variables[];
extern SHOW_VAR innodb_status_variables[];
extern uint innobase_init_flags, innobase_lock_type;
extern uint innobase_flush_log_at_trx_commit;
extern ulong innobase_cache_size, innobase_fast_shutdown;
......
......@@ -292,7 +292,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define OPTION_SETUP_TABLES_DONE (LL(1) << 30) // intern
/* If not set then the thread will ignore all warnings with level notes. */
#define OPTION_SQL_NOTES (LL(1) << 31) // THD, user
/*
/*
Force the used temporary table to be a MyISAM table (because we will use
fulltext functions when reading from it.
*/
......@@ -322,7 +322,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MODE_DB2 2048
#define MODE_MAXDB 4096
#define MODE_NO_KEY_OPTIONS 8192
#define MODE_NO_TABLE_OPTIONS 16384
#define MODE_NO_TABLE_OPTIONS 16384
#define MODE_NO_FIELD_OPTIONS 32768
#define MODE_MYSQL323 65536
#define MODE_MYSQL40 (MODE_MYSQL323*2)
......@@ -513,13 +513,11 @@ void free_items(Item *item);
void cleanup_items(Item *item);
class THD;
void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
bool check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables);
bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *tables);
bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
bool is_proc, bool no_errors);
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list);
bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list);
bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
......@@ -884,6 +882,10 @@ void calc_sum_of_all_status(STATUS_VAR *to);
void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
const LEX_STRING *definer_host);
int add_status_vars(SHOW_VAR *list);
void remove_status_vars(SHOW_VAR *list);
void init_status_vars();
void free_status_vars();
/* information schema */
extern LEX_STRING information_schema_name;
......@@ -1269,7 +1271,7 @@ extern I_List<NAMED_LIST> key_caches;
extern MY_BITMAP temp_pool;
extern String my_empty_string;
extern const String my_null_string;
extern SHOW_VAR init_vars[],status_vars[], internal_vars[];
extern SHOW_VAR init_vars[], status_vars[], internal_vars[];
extern struct system_variables global_system_variables;
extern struct system_variables max_system_variables;
extern struct system_status_var global_status_var;
......
......@@ -348,7 +348,7 @@ my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0;
my_bool opt_innodb;
#ifdef WITH_INNOBASE_STORAGE_ENGINE
extern struct show_var_st innodb_status_variables[];
extern SHOW_VAR innodb_status_variables[];
extern uint innobase_init_flags, innobase_lock_type;
extern uint innobase_flush_log_at_trx_commit;
extern ulong innobase_cache_size, innobase_fast_shutdown;
......@@ -417,7 +417,7 @@ ulong opt_ndb_cache_check_time;
const char *opt_ndb_mgmd;
ulong opt_ndb_nodeid;
extern struct show_var_st ndb_status_variables[];
extern SHOW_VAR ndb_status_variables[];
extern const char *ndb_distribution_names[];
extern TYPELIB ndb_distribution_typelib;
extern const char *opt_ndb_distribution;
......@@ -1154,18 +1154,19 @@ void clean_up(bool print_message)
set_var_free();
free_charsets();
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
#ifdef HAVE_DLOPEN
if (!opt_noacl)
{
#ifdef HAVE_DLOPEN
udf_free();
#endif
plugin_free();
}
#endif
plugin_free();
if (tc_log)
tc_log->close();
xid_cache_free();
delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
multi_keycache_free();
free_status_vars();
end_thr_alarm(1); /* Free allocated memory */
#ifdef USE_RAID
end_raid();
......@@ -2670,12 +2671,21 @@ static int init_common_variables(const char *conf_file_name, int argc,
mysql_log.init_pthread_objects();
mysql_slow_log.init_pthread_objects();
mysql_bin_log.init_pthread_objects();
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
strmov(glob_hostname,"mysql");
strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
/*
Add server status variables to the dynamic list of
status variables that is shown by SHOW STATUS.
Later, in plugin_init, plugin_load, and mysql_install_plugin
new entries could be added to that list.
*/
if (add_status_vars(status_vars))
return 1; // an error was already reported
if (plugin_init())
{
sql_print_error("Failed to init plugins.");
......@@ -3557,7 +3567,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
#ifndef __NETWARE__
(void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
#endif /* __NETWARE__ */
if (!opt_bootstrap)
(void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore
......@@ -3575,6 +3585,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
udf_init();
#endif
}
init_status_vars();
if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
opt_skip_slave_start= 1;
/*
......@@ -6186,39 +6197,39 @@ The minimum value for this variable is 4096.",
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
static int show_question(THD *thd, show_var_st *var, char *buff)
static int show_question(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONGLONG;
var->type= SHOW_LONGLONG;
var->value= (char *)&thd->query_id;
return 0;
}
static int show_net_compression(THD *thd, show_var_st *var, char *buff)
static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_MY_BOOL;
var->type= SHOW_MY_BOOL;
var->value= (char *)&thd->net.compress;
return 0;
}
static int show_starttime(THD *thd, show_var_st *var, char *buff)
static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long) (thd->query_start() - start_time);
return 0;
}
#ifdef HAVE_REPLICATION
static int show_rpl_status(THD *thd, show_var_st *var, char *buff)
static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_CHAR;
var->type= SHOW_CHAR;
var->value= const_cast<char*>(rpl_status_type[(int)rpl_status]);
return 0;
}
static int show_slave_running(THD *thd, show_var_st *var, char *buff)
static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_CHAR;
var->type= SHOW_CHAR;
pthread_mutex_lock(&LOCK_active_mi);
var->value= const_cast<char*>((active_mi && active_mi->slave_running &&
active_mi->rli.slave_running) ? "ON" : "OFF");
......@@ -6226,7 +6237,7 @@ static int show_slave_running(THD *thd, show_var_st *var, char *buff)
return 0;
}
static int show_slave_retried_trans(THD *thd, show_var_st *var, char *buff)
static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff)
{
/*
TODO: with multimaster, have one such counter per line in
......@@ -6235,30 +6246,30 @@ static int show_slave_retried_trans(THD *thd, show_var_st *var, char *buff)
pthread_mutex_lock(&LOCK_active_mi);
if (active_mi)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
pthread_mutex_lock(&active_mi->rli.data_lock);
*((long *)buff)= (long)active_mi->rli.retried_trans;
pthread_mutex_unlock(&active_mi->rli.data_lock);
}
else
var->type=SHOW_UNDEF;
var->type= SHOW_UNDEF;
pthread_mutex_unlock(&LOCK_active_mi);
return 0;
}
#endif /* HAVE_REPLICATION */
static int show_open_tables(THD *thd, show_var_st *var, char *buff)
static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long)cached_open_tables();
return 0;
}
static int show_table_definitions(THD *thd, show_var_st *var, char *buff)
static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long)cached_table_definitions();
return 0;
......@@ -6266,144 +6277,144 @@ static int show_table_definitions(THD *thd, show_var_st *var, char *buff)
#ifdef HAVE_OPENSSL
/* Functions relying on CTX */
static int show_ssl_ctx_sess_accept(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_accept_good(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_connect_good(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_cb_hits(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_hits(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_cache_full(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_misses(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_timeouts(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_number(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_connect(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_sess_get_cache_size(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_get_verify_mode(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_get_verify_depth(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (!ssl_acceptor_fd ? 0 :
SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
return 0;
}
static int show_ssl_ctx_get_session_cache_mode(THD *thd, show_var_st *var, char *buff)
static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_CHAR;
var->type= SHOW_CHAR;
if (!ssl_acceptor_fd)
var->value= "NONE";
else
......@@ -6428,26 +6439,26 @@ static int show_ssl_ctx_get_session_cache_mode(THD *thd, show_var_st *var, char
}
/* Functions relying on SSL */
static int show_ssl_get_version(THD *thd, show_var_st *var, char *buff)
static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_CHAR;
var->type= SHOW_CHAR;
var->value= const_cast<char*>(thd->net.vio->ssl_arg ?
SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
return 0;
}
static int show_ssl_session_reused(THD *thd, show_var_st *var, char *buff)
static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long)thd->net.vio->ssl_arg ?
SSL_session_reused((SSL*) thd->net.vio->ssl_arg) :
0;
}
static int show_ssl_get_default_timeout(THD *thd, show_var_st *var, char *buff)
static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long)thd->net.vio->ssl_arg ?
SSL_get_default_timeout((SSL*)thd->net.vio->ssl_arg) :
......@@ -6455,9 +6466,9 @@ static int show_ssl_get_default_timeout(THD *thd, show_var_st *var, char *buff)
return 0;
}
static int show_ssl_get_verify_mode(THD *thd, show_var_st *var, char *buff)
static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long)thd->net.vio->ssl_arg ?
SSL_get_verify_mode((SSL*)thd->net.vio->ssl_arg) :
......@@ -6465,9 +6476,9 @@ static int show_ssl_get_verify_mode(THD *thd, show_var_st *var, char *buff)
return 0;
}
static int show_ssl_get_verify_depth(THD *thd, show_var_st *var, char *buff)
static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_LONG;
var->type= SHOW_LONG;
var->value= buff;
*((long *)buff)= (long)thd->net.vio->ssl_arg ?
SSL_get_verify_depth((SSL*)thd->net.vio->ssl_arg) :
......@@ -6475,17 +6486,17 @@ static int show_ssl_get_verify_depth(THD *thd, show_var_st *var, char *buff)
return 0;
}
static int show_ssl_get_cipher(THD *thd, show_var_st *var, char *buff)
static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_CHAR;
var->type= SHOW_CHAR;
var->value= const_cast<char*>(thd->net.vio->ssl_arg ?
SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "");
return 0;
}
static int show_ssl_get_cipher_list(THD *thd, show_var_st *var, char *buff)
static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_CHAR;
var->type= SHOW_CHAR;
var->value= buff;
if (thd->net.vio->ssl_arg)
{
......@@ -6507,7 +6518,7 @@ static int show_ssl_get_cipher_list(THD *thd, show_var_st *var, char *buff)
#ifdef WITH_INNOBASE_STORAGE_ENGINE
int innodb_export_status(void);
static int show_innodb_vars(THD *thd, show_var_st *var, char *buff)
static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff)
{
innodb_export_status();
var->type= SHOW_ARRAY;
......@@ -6516,7 +6527,7 @@ static int show_innodb_vars(THD *thd, show_var_st *var, char *buff)
}
#endif
struct show_var_st status_vars[]= {
SHOW_VAR status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
{"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG},
......@@ -6547,7 +6558,7 @@ struct show_var_st status_vars[]= {
{"Com_drop_index", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
{"Com_drop_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
{"Com_drop_user", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS},
{"Com_execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
{"Com_execute_sql", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
{"Com_flush", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
{"Com_grant", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
{"Com_ha_close", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
......@@ -6626,14 +6637,14 @@ struct show_var_st status_vars[]= {
{"Com_xa_rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS},
{"Com_xa_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS},
{"Compression", (char*) &show_net_compression, SHOW_FUNC},
{"Connections", (char*) &thread_id, SHOW_LONG_CONST},
{"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH},
{"Created_tmp_disk_tables", (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
{"Created_tmp_files", (char*) &my_tmp_file_created, SHOW_LONG},
{"Created_tmp_tables", (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
{"Delayed_errors", (char*) &delayed_insert_errors, SHOW_LONG},
{"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_CONST},
{"Delayed_insert_threads", (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
{"Delayed_writes", (char*) &delayed_insert_writes, SHOW_LONG},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_CONST},
{"Flush_commands", (char*) &refresh_version, SHOW_LONG_NOFLUSH},
{"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
{"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
{"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
......@@ -6650,11 +6661,11 @@ struct show_var_st status_vars[]= {
{"Handler_update", (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
{"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
#ifdef WITH_INNOBASE_STORAGE_ENGINE
{"Innodb_", (char*) &show_innodb_vars, SHOW_FUNC},
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
#endif /* WITH_INNOBASE_STORAGE_ENGINE */
{"Key_blocks_not_flushed", (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG},
{"Key_blocks_unused", (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_CONST_LONG},
{"Key_blocks_used", (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_CONST_LONG},
{"Key_blocks_unused", (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG},
{"Key_blocks_used", (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG},
{"Key_read_requests", (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG},
{"Key_reads", (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG},
{"Key_write_requests", (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG},
......@@ -6662,23 +6673,23 @@ struct show_var_st status_vars[]= {
{"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
{"Ndb_", (char*) &ndb_status_variables, SHOW_ARRAY},
{"Ndb", (char*) &ndb_status_variables, SHOW_ARRAY},
#endif /* WITH_NDBCLUSTER_STORAGE_ENGINE */
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
{"Open_streams", (char*) &my_stream_opened, SHOW_LONG_CONST},
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_NOFLUSH},
{"Open_streams", (char*) &my_stream_opened, SHOW_LONG_NOFLUSH},
{"Open_table_definitions", (char*) &show_table_definitions, SHOW_FUNC},
{"Open_tables", (char*) &show_open_tables, SHOW_FUNC},
{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
#ifdef HAVE_QUERY_CACHE
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_CONST},
{"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_CONST},
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
{"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_lowmem_prunes", (char*) &query_cache.lowmem_prunes, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
{"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_CONST},
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH},
{"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH},
#endif /*HAVE_QUERY_CACHE*/
{"Questions", (char*) &show_question, SHOW_FUNC},
#ifdef HAVE_REPLICATION
......@@ -6732,10 +6743,10 @@ struct show_var_st status_vars[]= {
{"Tc_log_page_size", (char*) &tc_log_page_size, SHOW_LONG},
{"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG},
#endif
{"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_CONST},
{"Threads_connected", (char*) &thread_count, SHOW_INT_CONST},
{"Threads_created", (char*) &thread_created, SHOW_LONG_CONST},
{"Threads_running", (char*) &thread_running, SHOW_INT_CONST},
{"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_NOFLUSH},
{"Threads_connected", (char*) &thread_count, SHOW_INT},
{"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH},
{"Threads_running", (char*) &thread_running, SHOW_INT},
{"Uptime", (char*) &show_starttime, SHOW_FUNC},
{NullS, NullS, SHOW_LONG}
};
......
......@@ -624,7 +624,7 @@ sys_var_have_variable sys_have_row_based_replication("have_row_based_replication
sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE));
#ifdef HAVE_REPLICATION
static int show_slave_skip_errors(THD *thd, show_var_st *var, char *buff)
static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff)
{
var->type=SHOW_CHAR;
var->value= buff;
......@@ -667,7 +667,7 @@ static int show_slave_skip_errors(THD *thd, show_var_st *var, char *buff)
Variables shown by SHOW variables in alphabetical order
*/
struct show_var_st init_vars[]= {
SHOW_VAR init_vars[]= {
{"auto_increment_increment", (char*) &sys_auto_increment_increment, SHOW_SYS},
{"auto_increment_offset", (char*) &sys_auto_increment_offset, SHOW_SYS},
{sys_automatic_sp_privileges.name,(char*) &sys_automatic_sp_privileges, SHOW_SYS},
......
......@@ -6641,7 +6641,7 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
static void refresh_status(void)
{
pthread_mutex_lock(&LOCK_status);
for (struct show_var_st *ptr=status_vars; ptr->name; ptr++)
for (SHOW_VAR *ptr= status_vars; ptr->name; ptr++)
if (ptr->type == SHOW_LONG) // note that SHOW_LONG_NOFLUSH variables are not reset
*(ulong*) ptr->value= 0;
......
......@@ -94,7 +94,8 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl)
static inline void free_plugin_mem(struct st_plugin_dl *p)
{
dlclose(p->handle);
if (p->handle)
dlclose(p->handle);
my_free(p->dl.str, MYF(MY_ALLOW_ZERO_PTR));
if (p->version != MYSQL_PLUGIN_INTERFACE_VERSION)
my_free((gptr)p->plugins, MYF(MY_ALLOW_ZERO_PTR));
......@@ -182,7 +183,7 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report)
{
int i, sizeof_st_plugin;
struct st_mysql_plugin *old, *cur;
char *ptr=(char *)sym;
char *ptr= (char *)sym;
if ((sym= dlsym(plugin_dl.handle, sizeof_st_plugin_sym)))
sizeof_st_plugin= *(int *)sym;
......@@ -196,8 +197,12 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report)
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), sizeof_st_plugin_sym);
DBUG_RETURN(0);
#else
/*
When the following assert starts failing, we'll have to switch
to the upper branch of the #ifdef
*/
DBUG_ASSERT(min_plugin_interface_version == 0);
sizeof_st_plugin=(int)offsetof(struct st_mysql_plugin, version);
sizeof_st_plugin= (int)offsetof(struct st_mysql_plugin, version);
#endif
}
......@@ -217,29 +222,17 @@ static st_plugin_dl *plugin_dl_add(LEX_STRING *dl, int report)
sql_print_error(ER(ER_OUTOFMEMORY), plugin_dl.dl.length);
DBUG_RETURN(0);
}
/*
All st_plugin fields not initialized in the plugin explicitly, are
set to 0. It matches C standard behaviour for struct initializers that
have less values than the struct definition.
*/
for (i=0;
(old=(struct st_mysql_plugin *)(ptr+i*sizeof_st_plugin))->info;
i++)
{
switch (plugin_dl.version) {
default: /* version > MYSQL_PLUGIN_INTERFACE_VERSION */
/* fall through */
case 0x0001:
cur[i].version=old->version;
// cur[i].status_vars=old->status_vars;
/* fall through */
case 0x0000:
cur[i].type=old->type;
cur[i].info=old->info;
cur[i].name=old->name;
cur[i].author=old->author;
cur[i].descr=old->descr;
cur[i].init=old->init;
cur[i].deinit=old->deinit;
}
}
memcpy(cur+i, old, min(sizeof(cur[i]), sizeof_st_plugin));
sym=cur;
sym= cur;
}
plugin_dl.plugins= (struct st_mysql_plugin *)sym;
......@@ -320,7 +313,7 @@ static struct st_plugin_int *plugin_find_internal(LEX_STRING *name, int type)
{
struct st_plugin_int *plugin= (st_plugin_int *)
hash_search(&plugin_hash[i], (const byte *)name->str, name->length);
if (plugin)
if (plugin)
DBUG_RETURN(plugin);
}
}
......@@ -382,7 +375,6 @@ static st_plugin_int *plugin_insert_or_reuse(struct st_plugin_int *plugin)
struct st_plugin_int *));
}
static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report)
{
struct st_plugin_int tmp;
......@@ -429,21 +421,20 @@ static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report)
tmp.name.length= name_len;
tmp.ref_count= 0;
tmp.state= PLUGIN_IS_UNINITIALIZED;
if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
if (plugin->status_vars)
{
if (report & REPORT_TO_USER)
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_int));
if (report & REPORT_TO_LOG)
sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_int));
goto err;
SHOW_VAR array[2]= {
{plugin->name, (char*)plugin->status_vars, SHOW_ARRAY},
{0, 0, SHOW_UNDEF}
};
if (add_status_vars(array)) // add_status_vars makes a copy
goto err;
}
if (! (tmp_plugin_ptr= plugin_insert_or_reuse(&tmp)))
goto err;
if (my_hash_insert(&plugin_hash[plugin->type], (byte*)tmp_plugin_ptr))
{
tmp_plugin_ptr->state= PLUGIN_IS_FREED;
if (report & REPORT_TO_USER)
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_int));
if (report & REPORT_TO_LOG)
sql_print_error(ER(ER_OUTOFMEMORY), sizeof(struct st_plugin_int));
goto err;
}
DBUG_RETURN(FALSE);
......@@ -454,6 +445,14 @@ static my_bool plugin_add(LEX_STRING *name, LEX_STRING *dl, int report)
if (report & REPORT_TO_LOG)
sql_print_error(ER(ER_CANT_FIND_DL_ENTRY), name->str);
err:
if (plugin->status_vars)
{
SHOW_VAR array[2]= {
{plugin->name, (char*)plugin->status_vars, SHOW_ARRAY},
{0, 0, SHOW_UNDEF}
};
remove_status_vars(array);
}
plugin_dl_del(dl);
DBUG_RETURN(TRUE);
}
......@@ -466,6 +465,14 @@ static void plugin_del(LEX_STRING *name)
DBUG_ENTER("plugin_del");
if ((plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
{
if (plugin->plugin->status_vars)
{
SHOW_VAR array[2]= {
{plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY},
{0, 0, SHOW_UNDEF}
};
remove_status_vars(array);
}
hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin);
plugin_dl_del(&plugin->plugin_dl->dl);
plugin->state= PLUGIN_IS_FREED;
......@@ -494,7 +501,7 @@ void plugin_unlock(struct st_plugin_int *plugin)
static int plugin_initialize(struct st_plugin_int *plugin)
{
DBUG_ENTER("plugin_initialize");
if (plugin->plugin->init)
{
if (plugin->plugin->init())
......@@ -506,7 +513,7 @@ static int plugin_initialize(struct st_plugin_int *plugin)
goto err;
}
}
switch (plugin->plugin->type)
{
case MYSQL_STORAGE_ENGINE_PLUGIN:
......@@ -605,11 +612,11 @@ int plugin_init(void)
get_hash_key, NULL, 0))
goto err;
}
initialized= 1;
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
}
......@@ -651,9 +658,9 @@ void plugin_load(void)
MEM_ROOT mem;
THD *new_thd;
DBUG_ENTER("plugin_load");
DBUG_ASSERT(initialized);
if (!(new_thd= new THD))
{
sql_print_error("Can't allocate memory for plugin structures");
......@@ -716,12 +723,7 @@ void plugin_free(void)
{
struct st_plugin_dl *tmp= dynamic_element(&plugin_dl_array, i,
struct st_plugin_dl *);
#ifdef HAVE_DLOPEN
if (tmp->handle)
{
free_plugin_mem(tmp);
}
#endif
free_plugin_mem(tmp);
}
delete_dynamic(&plugin_dl_array);
if (initialized)
......@@ -746,7 +748,7 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl)
tables.table_name= tables.alias= (char *)"plugin";
if (check_table_access(thd, INSERT_ACL, &tables, 0))
DBUG_RETURN(TRUE);
/* need to open before acquiring THR_LOCK_plugin or it will deadlock */
if (! (table = open_ltable(thd, &tables, TL_WRITE)))
DBUG_RETURN(TRUE);
......@@ -755,7 +757,7 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl)
if (plugin_add(name, dl, REPORT_TO_USER))
goto err;
tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN);
if (plugin_initialize(tmp))
{
my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
......@@ -774,7 +776,7 @@ my_bool mysql_install_plugin(THD *thd, LEX_STRING *name, LEX_STRING *dl)
table->file->print_error(error, MYF(0));
goto deinit;
}
rw_unlock(&THR_LOCK_plugin);
DBUG_RETURN(FALSE);
deinit:
......@@ -815,7 +817,7 @@ my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name)
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
goto err;
}
if (plugin->ref_count)
{
plugin->state= PLUGIN_IS_DELETED;
......@@ -858,13 +860,13 @@ my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
struct st_plugin_int *plugin;
DBUG_ENTER("mysql_uninstall_plugin");
rw_rdlock(&THR_LOCK_plugin);
if (type == MYSQL_ANY_PLUGIN)
{
for (idx= 0; idx < plugin_array.elements; idx++)
{
plugin= dynamic_element(&plugin_array, idx, struct st_plugin_int *);
/* FREED records may have garbage pointers */
if ((plugin->state != PLUGIN_IS_FREED) &&
func(thd, plugin, arg))
......
......@@ -17,7 +17,17 @@
#ifndef _sql_plugin_h
#define _sql_plugin_h
/*
the following #define adds server-only members to enum_mysql_show_type,
that is defined in plugin.h
*/
#define SHOW_FUNC SHOW_FUNC, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_LONGLONG, \
SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, SHOW_HAVE, \
SHOW_HA_ROWS, SHOW_SYS, SHOW_LONG_NOFLUSH
#include <plugin.h>
#undef SHOW_FUNC
typedef enum enum_mysql_show_type SHOW_TYPE;
typedef struct st_mysql_show_var SHOW_VAR;
#define MYSQL_ANY_PLUGIN -1
......@@ -65,7 +75,7 @@ extern my_bool mysql_uninstall_plugin(THD *thd, LEX_STRING *name);
extern my_bool plugin_register_builtin(struct st_mysql_plugin *plugin);
typedef my_bool (plugin_foreach_func)(THD *thd,
typedef my_bool (plugin_foreach_func)(THD *thd,
st_plugin_int *plugin,
void *arg);
extern my_bool plugin_foreach(THD *thd, plugin_foreach_func *func,
......
......@@ -1516,8 +1516,163 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
Status functions
*****************************************************************************/
static DYNAMIC_ARRAY all_status_vars;
static bool status_vars_inited= 0;
static int show_var_cmp(const void *var1, const void *var2)
{
return strcmp(((SHOW_VAR*)var1)->name, ((SHOW_VAR*)var2)->name);
}
/*
deletes all the SHOW_UNDEF elements from the array and calls
delete_dynamic() if it's completely empty.
*/
static void shrink_var_array(DYNAMIC_ARRAY *array)
{
int a,b;
SHOW_VAR *all= dynamic_element(array, 0, SHOW_VAR *);
for (a= b= 0; b < array->elements; b++)
if (all[b].type != SHOW_UNDEF)
all[a++]= all[b];
if (a)
{
bzero(all+a, sizeof(SHOW_VAR)); // writing NULL-element to the end
array->elements= a;
}
else // array is completely empty - delete it
delete_dynamic(array);
}
/*
Adds an array of SHOW_VAR entries to the output of SHOW STATUS
SYNOPSIS
add_status_vars(SHOW_VAR *list)
list - an array of SHOW_VAR entries to add to all_status_vars
the last entry must be {0,0,SHOW_UNDEF}
NOTE
The handling of all_status_vars[] is completely internal, it's allocated
automatically when something is added to it, and deleted completely when
the last entry is removed.
As a special optimization, if add_status_vars() is called before
init_status_vars(), it assumes "startup mode" - neither concurrent access
to the array nor SHOW STATUS are possible (thus it skips locks and qsort)
The last entry of the all_status_vars[] should always be {0,0,SHOW_UNDEF}
*/
int add_status_vars(SHOW_VAR *list)
{
int res= 0;
if (status_vars_inited)
pthread_mutex_lock(&LOCK_status);
if (!all_status_vars.buffer && // array is not allocated yet - do it now
my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20))
{
res= 1;
goto err;
}
while (list->name)
res|= insert_dynamic(&all_status_vars, (gptr)list++);
res|= insert_dynamic(&all_status_vars, (gptr)list); // appending NULL-element
all_status_vars.elements--; // but next insert_dynamic should overwite it
if (status_vars_inited)
sort_dynamic(&all_status_vars, show_var_cmp);
err:
if (status_vars_inited)
pthread_mutex_unlock(&LOCK_status);
return res;
}
/*
Make all_status_vars[] usable for SHOW STATUS
NOTE
See add_status_vars(). Before init_status_vars() call, add_status_vars()
works in a special fast "startup" mode. Thus init_status_vars()
should be called as late as possible but before enabling multi-threading.
*/
void init_status_vars()
{
status_vars_inited=1;
sort_dynamic(&all_status_vars, show_var_cmp);
}
/*
catch-all cleanup function, cleans up everything no matter what
DESCRIPTION
This function is not strictly required if all add_to_status/
remove_status_vars are properly paired, but it's a safety measure that
deletes everything from the all_status_vars[] even if some
remove_status_vars were forgotten
*/
void free_status_vars()
{
delete_dynamic(&all_status_vars);
}
/*
Removes an array of SHOW_VAR entries from the output of SHOW STATUS
SYNOPSIS
remove_status_vars(SHOW_VAR *list)
list - an array of SHOW_VAR entries to remove to all_status_vars
the last entry must be {0,0,SHOW_UNDEF}
NOTE
there's lots of room for optimizing this, especially in non-sorted mode,
but nobody cares - it may be called only in case of failed plugin
initialization in the mysqld startup.
*/
void remove_status_vars(SHOW_VAR *list)
{
if (status_vars_inited)
{
pthread_mutex_lock(&LOCK_status);
SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
int a= 0, b= all_status_vars.elements, c= (a+b)/2, res;
for (; list->name; list++)
{
for (a= 0, b= all_status_vars.elements; b-a > 1; c= (a+b)/2)
{
res= show_var_cmp(list, all+c);
if (res < 0)
b= c;
else if (res > 0)
a= c;
else break;
}
if (res == 0)
all[c].type= SHOW_UNDEF;
}
shrink_var_array(&all_status_vars);
pthread_mutex_unlock(&LOCK_status);
}
else
{
SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *);
int i;
for (; list->name; list++)
{
for (i= 0; i < all_status_vars.elements; i++)
{
if (show_var_cmp(list, all+i))
continue;
all[i].type= SHOW_UNDEF;
break;
}
}
shrink_var_array(&all_status_vars);
}
}
static bool show_status_array(THD *thd, const char *wild,
show_var_st *variables,
SHOW_VAR *variables,
enum enum_var_type value_type,
struct system_status_var *status_var,
const char *prefix, TABLE *table)
......@@ -1527,13 +1682,15 @@ static bool show_status_array(THD *thd, const char *wild,
char name_buffer[80];
int len;
LEX_STRING null_lex_str;
struct show_var_st tmp, *var;
SHOW_VAR tmp, *var;
DBUG_ENTER("show_status_array");
null_lex_str.str= 0; // For sys_var->value_ptr()
null_lex_str.length= 0;
prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
if (*prefix)
*prefix_end++= '_';
len=name_buffer + sizeof(name_buffer) - prefix_end;
for (; variables->name; variables++)
......@@ -1541,13 +1698,17 @@ static bool show_status_array(THD *thd, const char *wild,
strnmov(prefix_end, variables->name, len);
name_buffer[sizeof(name_buffer)-1]=0; /* Safety */
/*
if var->type is SHOW_FUNC, call the function.
Repeat as necessary, if new var is again SHOW_FUNC
*/
for (var=variables; var->type == SHOW_FUNC; var= &tmp)
((show_var_func)(var->value))(thd, &tmp, buff);
((mysql_show_var_func)(var->value))(thd, &tmp, buff);
SHOW_TYPE show_type=var->type;
if (show_type == SHOW_ARRAY)
{
show_status_array(thd, wild, (show_var_st *) var->value,
show_status_array(thd, wild, (SHOW_VAR *) var->value,
value_type, status_var, name_buffer, table);
}
else
......@@ -1578,11 +1739,10 @@ static bool show_status_array(THD *thd, const char *wild,
break;
}
case SHOW_LONG_STATUS:
case SHOW_LONG_CONST_STATUS:
value= ((char *) status_var + (ulong) value);
/* fall through */
case SHOW_LONG:
case SHOW_LONG_CONST:
case SHOW_LONG_NOFLUSH: // the difference lies in refresh_status()
end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_LONGLONG:
......@@ -1597,7 +1757,6 @@ static bool show_status_array(THD *thd, const char *wild,
case SHOW_MY_BOOL:
end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
break;
case SHOW_INT_CONST:
case SHOW_INT:
end= int10_to_str((long) *(uint32*) value, buff, 10);
break;
......@@ -1623,7 +1782,6 @@ static bool show_status_array(THD *thd, const char *wild,
break;
}
case SHOW_KEY_CACHE_LONG:
case SHOW_KEY_CACHE_CONST_LONG:
value= (char*) dflt_key_cache + (ulong)value;
end= int10_to_str(*(long*) value, buff, 10);
break;
......@@ -1632,9 +1790,10 @@ static bool show_status_array(THD *thd, const char *wild,
end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
case SHOW_UNDEF:
case SHOW_SYS:
break; // Return empty string
break; // Return empty string
case SHOW_SYS: // Cannot happen
default:
DBUG_ASSERT(0);
break;
}
restore_record(table, s->default_values);
......@@ -3357,7 +3516,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond)
LEX *lex= thd->lex;
const char *wild= lex->wild ? lex->wild->ptr() : NullS;
pthread_mutex_lock(&LOCK_global_system_variables);
res= show_status_array(thd, wild, init_vars,
res= show_status_array(thd, wild, init_vars,
lex->option_type, 0, "", tables->table);
pthread_mutex_unlock(&LOCK_global_system_variables);
DBUG_RETURN(res);
......@@ -3374,8 +3533,10 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
pthread_mutex_lock(&LOCK_status);
if (lex->option_type == OPT_GLOBAL)
calc_sum_of_all_status(&tmp);
res= show_status_array(thd, wild, status_vars, OPT_GLOBAL,
(lex->option_type == OPT_GLOBAL ?
res= show_status_array(thd, wild,
(SHOW_VAR *)all_status_vars.buffer,
OPT_GLOBAL,
(lex->option_type == OPT_GLOBAL ?
&tmp: &thd->status_var), "",tables->table);
pthread_mutex_unlock(&LOCK_status);
DBUG_RETURN(res);
......@@ -4146,7 +4307,7 @@ ST_FIELD_INFO plugin_fields_info[]=
{"PLUGIN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
{"PLUGIN_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0},
{"PLUGIN_STATUS", 10, MYSQL_TYPE_STRING, 0, 0, "Status"},
{"PLUGIN_TYPE", 10, MYSQL_TYPE_STRING, 0, 0, "Type"},
{"PLUGIN_TYPE", 80, MYSQL_TYPE_STRING, 0, 0, "Type"},
{"PLUGIN_TYPE_VERSION", 20, MYSQL_TYPE_STRING, 0, 0, 0},
{"PLUGIN_LIBRARY", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Library"},
{"PLUGIN_LIBRARY_VERSION", 20, MYSQL_TYPE_STRING, 0, 1, 0},
......
......@@ -169,32 +169,11 @@ typedef struct st_known_date_time_format {
const char *time_format;
} KNOWN_DATE_TIME_FORMAT;
enum SHOW_TYPE
{
SHOW_UNDEF,
SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR,
SHOW_DOUBLE_STATUS, SHOW_BOOL, SHOW_MY_BOOL,
SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
SHOW_ARRAY, SHOW_FUNC,
SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_CONST_LONG, SHOW_KEY_CACHE_LONGLONG,
SHOW_LONG_STATUS, SHOW_LONG_CONST_STATUS
};
enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED};
extern const char *show_comp_option_name[];
typedef int *(*update_var)(THD *, struct show_var_st *);
typedef struct show_var_st {
const char *name;
char *value;
SHOW_TYPE type;
} SHOW_VAR;
#define SHOW_VAR_FUNC_BUFF_SIZE 1024
typedef int (*show_var_func)(THD *, struct show_var_st *, char *);
typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
typedef struct st_lex_user {
LEX_STRING user, host, password;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment