summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/plugin.h22
-rw-r--r--plugin/fulltext/plugin_example.c18
-rw-r--r--sql/ha_innodb.cc2
-rw-r--r--sql/ha_innodb.h2
-rw-r--r--sql/mysql_priv.h16
-rw-r--r--sql/mysqld.cc193
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sql_parse.cc2
-rw-r--r--sql/sql_plugin.cc106
-rw-r--r--sql/sql_plugin.h12
-rw-r--r--sql/sql_show.cc189
-rw-r--r--sql/structs.h23
12 files changed, 395 insertions, 194 deletions
diff --git a/include/plugin.h b/include/plugin.h
index 3faa02cb079..6c571b8504b 100644
--- a/include/plugin.h
+++ b/include/plugin.h
@@ -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;
};
/*************************************************************************
diff --git a/plugin/fulltext/plugin_example.c b/plugin/fulltext/plugin_example.c
index c222d3d85c3..4caa6de3197 100644
--- a/plugin/fulltext/plugin_example.c
+++ b/plugin/fulltext/plugin_example.c
@@ -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;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 27262e6f197..75c1c380a42 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -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",
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 8db7f00ffa9..b9e399509de 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -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;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index b6be03003c6..e9b79afff7a 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 59c317d724e..f40f27d5a32 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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}
};
diff --git a/sql/set_var.cc b/sql/set_var.cc
index dfd451442ca..377b4fd6f3f 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -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},
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 2c72c52a05b..ea9f8c6ffd2 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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;
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 9c3d19369c8..4e156fb7c11 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -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))
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index f0b70ca9d26..ce06334ffd7 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -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,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index e5723b27b5c..0de02337fff 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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},
diff --git a/sql/structs.h b/sql/structs.h
index d16591c5453..e369d8ed7e8 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -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;