diff options
-rw-r--r-- | include/plugin.h | 22 | ||||
-rw-r--r-- | plugin/fulltext/plugin_example.c | 18 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 2 | ||||
-rw-r--r-- | sql/ha_innodb.h | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 16 | ||||
-rw-r--r-- | sql/mysqld.cc | 193 | ||||
-rw-r--r-- | sql/set_var.cc | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_plugin.cc | 106 | ||||
-rw-r--r-- | sql/sql_plugin.h | 12 | ||||
-rw-r--r-- | sql/sql_show.cc | 189 | ||||
-rw-r--r-- | sql/structs.h | 23 |
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; |