From 3c78bfe7f1a1530daea83f5dae091bd654ea6d37 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 1 Jul 2011 15:08:30 +0300 Subject: Added progress reporting for alter table, LOAD DATA INFILE and for aria tables: check table, repair table, analyze table. - The client gets a progress report message that triggers a callback function if requested with mysql_options(MYSQL_PROGRESS_CALLBACK, function) - Added Progress field last to 'show processlist' - Stage, Max_stage and Progress field added to information_schema.progresslist - The 'mysql' client by defaults enables progress reports when the output is a tty. - Added progress_report_time time variable to configure how often progress reports is sent to client Added read only system variable 'in_transaction' which is 1 if we have executed a BEGIN statement. client/client_priv.h: Added OPT_REPORT_PROGRESS client/mysql.cc: Added option --progress-reports (on by default if not batch mode) Progress reports is written to stdout for long running commands include/Makefile.am: Added mysql/service_progress_report.h include/myisamchk.h: Added variables to be able to do progress reporting in Aria and later in MyISAM include/mysql.h: Added new mysql_options() parameter: MYSQL_PROGRESS_CALLBACK include/mysql.h.pp: Added new mysql_options() parameter: MYSQL_PROGRESS_CALLBACK include/mysql/plugin.h: Added functions for reporting progress. include/mysql/plugin_auth.h.pp: Added functions for reporting progress. include/mysql_com.h: Added CLIENT_PROGRESS mysql_real_connect() flag. include/sql_common.h: Added callback function for reporting progress mysql-test/r/old-mode.result: Ensure that SHOW PROGRESSLIST doesn't have the Progress column in old mode. mysql-test/suite/funcs_1/datadict/datadict_priv.inc: Added new column mysql-test/suite/funcs_1/datadict/processlist_priv.inc: Test all new PROCESSLIST columns mysql-test/suite/funcs_1/r/is_columns_is.result: Updated results mysql-test/suite/funcs_1/r/is_columns_is_embedded.result: Updated results mysql-test/suite/funcs_1/r/is_columns_mysql_embedded.result: Updated results mysql-test/suite/funcs_1/r/is_tables_is_embedded.result: Updated results mysql-test/suite/funcs_1/r/processlist_priv_no_prot.result: Updated results mysql-test/suite/funcs_1/r/processlist_priv_ps.result: Updated results mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: Updated results mysql-test/suite/funcs_1/r/processlist_val_ps.result: Updated results mysql-test/suite/pbxt/r/pbxt_locking.result: Updated results mysql-test/suite/pbxt/r/skip_name_resolve.result: Updated results mysql-test/t/old-mode.test: Ensure that SHOW PROGRESSLIST doesn't have the Progress column in old mode. plugin/handler_socket/handlersocket/Makefile.am: Added -lmysqlservices scripts/mytop.sh: Made 'State' field width dynamic. Added 'Progress' to process list display. sql-common/client.c: Added handling of progress messages. Removed check_license() function. sql/mysql_priv.h: Added opt_progress_report_time sql/mysqld.cc: Added progress_report_time time variable to configure how often progress reports is sent to client sql/protocol.cc: Added net_send_progress_packet() sql/protocol.h: New prototypes sql/set_var.cc: Added variables progress_report_time and in_transaction sql/sql_acl.cc: Safety fix: Made client_capabilities ulonglong sql/sql_class.cc: Added interface functions for progress reporting sql/sql_class.h: Added varibles in THD for progress reporting. Added CF_REPORT_PROGRESS sql/sql_load.cc: Added progress reporting for LOAD DATA INFILE sql/sql_parse.cc: Added CF_REPORT_PROGRESS for top level commands for which it's safe to send progress reports to client sql/sql_show.cc: Added Progress field last to 'show processlist' Stage, Max_stage and Progress field added to information_schema.progresslist sql/sql_table.cc: Added progress reporting for ALTER TABLE Added THD as argument to copy_data_between_tables() storage/maria/ha_maria.cc: Added progress reporting for check table, repair table, analyze table Fixed a bug in start_bulk_insert() that caused alter table to always run with all keys enabled. storage/maria/ma_check.c: Added progress reporting Remember old state before starting repair. This removes some warnings from optimize_table if create-with-sort fails. storage/maria/ma_check_standalone.h: Added dummy reporting function for standalone Aria programs. storage/maria/ma_sort.c: Added progress reporting storage/maria/maria_chk.c: Updated version storage/maria/maria_def.h: Added new prototypes tests/mysql_client_test.c: Added test case for progress reporting --- sql/sql_class.cc | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) (limited to 'sql/sql_class.cc') diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3bd1e591054..0772ea56d17 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -725,6 +725,8 @@ THD::THD() user_time.val= start_time= start_time_sec_part= 0; start_utime= prior_thr_create_utime= 0L; utime_after_lock= 0L; + progress.report_to_client= 0; + progress.max_counter= 0; current_linfo = 0; slave_thread = 0; bzero(&variables, sizeof(variables)); @@ -991,6 +993,11 @@ void THD::update_all_stats() ulonglong end_cpu_time, end_utime; double busy_time, cpu_time; + /* Reset status variables used by information_schema.processlist */ + progress.max_counter= 0; + progress.max_stage= 0; + progress.report= 0; + /* This is set at start of query if opt_userstat_running was set */ if (!userstat_running) return; @@ -3364,11 +3371,123 @@ void THD::restore_backup_open_tables_state(Open_tables_state *backup) @retval 0 the user thread is active @retval 1 the user thread has been killed */ + extern "C" int thd_killed(const MYSQL_THD thd) { return(thd->killed); } + +/** + Send an out-of-band progress report to the client + + The report is sent every 'thd->...progress_report_time' second, + however not more often than global.progress_report_time. + If global.progress_report_time is 0, then don't send progress reports, but + check every second if the value has changed +*/ + +static void thd_send_progress(THD *thd) +{ + /* Check if we should send the client a progress report */ + ulonglong report_time= my_interval_timer(); + if (report_time > thd->progress.next_report_time) + { + uint seconds_to_next= max(thd->variables.progress_report_time, + global_system_variables.progress_report_time); + if (seconds_to_next == 0) // Turned off + seconds_to_next= 1; // Check again after 1 second + + thd->progress.next_report_time= (report_time + + seconds_to_next * 1000000000ULL); + if (global_system_variables.progress_report_time && + thd->variables.progress_report_time) + net_send_progress_packet(thd); + } +} + + +/** Initialize progress report handling **/ + +extern "C" void thd_progress_init(MYSQL_THD thd, uint max_stage) +{ + /* + Send progress reports to clients that supports it, if the command + is a high level command (like ALTER TABLE) and we are not in a + stored procedure + */ + thd->progress.report= ((thd->client_capabilities & CLIENT_PROGRESS) && + thd->progress.report_to_client && + !thd->in_sub_stmt); + thd->progress.next_report_time= 0; + thd->progress.stage= 0; + thd->progress.counter= thd->progress.max_counter= 0; + thd->progress.max_stage= max_stage; +} + + +/* Inform processlist and the client that some progress has been made */ + +extern "C" void thd_progress_report(MYSQL_THD thd, + ulonglong progress, ulonglong max_progress) +{ + if (thd->progress.max_counter != max_progress) // Simple optimization + { + pthread_mutex_lock(&thd->LOCK_thd_data); + thd->progress.counter= progress; + thd->progress.max_counter= max_progress; + pthread_mutex_unlock(&thd->LOCK_thd_data); + } + else + thd->progress.counter= progress; + + if (thd->progress.report) + thd_send_progress(thd); +} + +/** + Move to next stage in process list handling + + This will reset the timer to ensure the progress is sent to the client + if client progress reports are activated. +*/ + +extern "C" void thd_progress_next_stage(MYSQL_THD thd) +{ + pthread_mutex_lock(&thd->LOCK_thd_data); + thd->progress.stage++; + thd->progress.counter= 0; + DBUG_ASSERT(thd->progress.stage < thd->progress.max_stage); + pthread_mutex_unlock(&thd->LOCK_thd_data); + if (thd->progress.report) + { + thd->progress.next_report_time= 0; // Send new stage info + thd_send_progress(thd); + } +} + +/** + Disable reporting of progress in process list. + + @note + This function is safe to call even if one has not called thd_progress_init. + + This function should be called by all parts that does progress + reporting to ensure that progress list doesn't contain 100 % done + forever. +*/ + + +extern "C" void thd_progress_end(MYSQL_THD thd) +{ + /* + It's enough to reset max_counter to set disable progress indicator + in processlist. + */ + thd->progress.max_counter= 0; +} + + /** Return the thread id of a user thread @param thd user thread -- cgit v1.2.1