diff options
author | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-03-24 18:03:44 +0300 |
---|---|---|
committer | Alexey Kopytov <Alexey.Kopytov@Sun.com> | 2010-03-24 18:03:44 +0300 |
commit | d95c1e3b470506c7df6dfce3fe6dc7e5b46930ee (patch) | |
tree | 9f13d4fcc3ac732dc94fe2cae446f6f8c2b4e02b /sql/events.cc | |
parent | abc6846d5b1df4846c4ffc03f4c93c82f874dd96 (diff) | |
parent | ae715642f46d4ed9ea8b5dd9b5cc9f3cace7f437 (diff) | |
download | mariadb-git-d95c1e3b470506c7df6dfce3fe6dc7e5b46930ee.tar.gz |
Manual merge of mysql-trunk into mysql-trunk-merge.
Conflicts:
Text conflict in client/mysqlbinlog.cc
Text conflict in mysql-test/Makefile.am
Text conflict in mysql-test/collections/default.daily
Text conflict in mysql-test/r/mysqlbinlog_row_innodb.result
Text conflict in mysql-test/suite/rpl/r/rpl_typeconv_innodb.result
Text conflict in mysql-test/suite/rpl/t/rpl_get_master_version_and_clock.test
Text conflict in mysql-test/suite/rpl/t/rpl_row_create_table.test
Text conflict in mysql-test/suite/rpl/t/rpl_slave_skip.test
Text conflict in mysql-test/suite/rpl/t/rpl_typeconv_innodb.test
Text conflict in mysys/charset.c
Text conflict in sql/field.cc
Text conflict in sql/field.h
Text conflict in sql/item.h
Text conflict in sql/item_func.cc
Text conflict in sql/log.cc
Text conflict in sql/log_event.cc
Text conflict in sql/log_event_old.cc
Text conflict in sql/mysqld.cc
Text conflict in sql/rpl_utility.cc
Text conflict in sql/rpl_utility.h
Text conflict in sql/set_var.cc
Text conflict in sql/share/Makefile.am
Text conflict in sql/sql_delete.cc
Text conflict in sql/sql_plugin.cc
Text conflict in sql/sql_select.cc
Text conflict in sql/sql_table.cc
Text conflict in storage/example/ha_example.h
Text conflict in storage/federated/ha_federated.cc
Text conflict in storage/myisammrg/ha_myisammrg.cc
Text conflict in storage/myisammrg/myrg_open.c
Diffstat (limited to 'sql/events.cc')
-rw-r--r-- | sql/events.cc | 337 |
1 files changed, 110 insertions, 227 deletions
diff --git a/sql/events.cc b/sql/events.cc index f6c4ea6d54f..a2375b1274b 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -11,7 +11,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mysql_priv.h" #include "events.h" @@ -20,6 +20,7 @@ #include "event_queue.h" #include "event_scheduler.h" #include "sp_head.h" // for Stored_program_creation_ctx +#include "set_var.h" /** @addtogroup Event_Scheduler @@ -63,44 +64,11 @@ eligible for execution. */ -/* - Keep the order of the first to as in var_typelib - sys_var_event_scheduler::value_ptr() references this array. Keep in - mind! -*/ -static const char *opt_event_scheduler_state_names[]= - { "OFF", "ON", "0", "1", "DISABLED", NullS }; - -const TYPELIB Events::opt_typelib= -{ - array_elements(opt_event_scheduler_state_names)-1, - "", - opt_event_scheduler_state_names, - NULL -}; - - -/* - The order should not be changed. We consider OFF to be equivalent of INT 0 - And ON of 1. If OFF & ON are interchanged the logic in - sys_var_event_scheduler::update() will be broken! -*/ -static const char *var_event_scheduler_state_names[]= { "OFF", "ON", NullS }; - -const TYPELIB Events::var_typelib= -{ - array_elements(var_event_scheduler_state_names)-1, - "", - var_event_scheduler_state_names, - NULL -}; - Event_queue *Events::event_queue; Event_scheduler *Events::scheduler; Event_db_repository *Events::db_repository; -enum Events::enum_opt_event_scheduler -Events::opt_event_scheduler= Events::EVENTS_OFF; -pthread_mutex_t Events::LOCK_event_metadata; +uint Events::opt_event_scheduler= Events::EVENTS_OFF; +mysql_mutex_t Events::LOCK_event_metadata; bool Events::check_system_tables_error= FALSE; @@ -127,69 +95,6 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs) /** - @brief Initialize the start up option of the Events scheduler. - - Do not initialize the scheduler subsystem yet - the initialization - is split into steps as it has to fit into the common MySQL - initialization framework. - No locking as this is called only at start up. - - @param[in,out] argument The value of the argument. If this value - is found in the typelib, the argument is - updated. - - @retval TRUE unknown option value - @retval FALSE success -*/ - -bool -Events::set_opt_event_scheduler(char *argument) -{ - if (argument == NULL) - opt_event_scheduler= Events::EVENTS_ON; - else - { - int type; - /* - type= 1 2 3 4 5 - (OFF | ON) - (0 | 1) (DISABLE ) - */ - const static enum enum_opt_event_scheduler type2state[]= - { EVENTS_OFF, EVENTS_ON, EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED }; - - type= find_type(argument, &opt_typelib, 1); - - DBUG_ASSERT(type >= 0 && type <= 5); /* guaranteed by find_type */ - - if (type == 0) - { - fprintf(stderr, "Unknown option to event-scheduler: %s\n", argument); - return TRUE; - } - opt_event_scheduler= type2state[type-1]; - } - return FALSE; -} - - -/** - Return a string representation of the current scheduler mode. -*/ - -const char * -Events::get_opt_event_scheduler_str() -{ - const char *str; - - pthread_mutex_lock(&LOCK_event_metadata); - str= opt_typelib.type_names[(int) opt_event_scheduler]; - pthread_mutex_unlock(&LOCK_event_metadata); - - return str; -} - - -/** Push an error into the error stack if the system tables are not up to date. */ @@ -392,15 +297,6 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, bool save_binlog_row_based; DBUG_ENTER("Events::create_event"); - /* - Let's commit the transaction first - MySQL manual specifies - that a DDL issues an implicit commit, and it doesn't say "successful - DDL", so that an implicit commit is a property of any successfully - parsed DDL statement. - */ - if (end_active_trans(thd)) - DBUG_RETURN(TRUE); - if (check_if_system_tables_error()) DBUG_RETURN(TRUE); @@ -415,9 +311,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, /* At create, one of them must be set */ DBUG_ASSERT(parse_data->expression || parse_data->execute_at); - if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0, - is_schema_db(parse_data->dbname.str, - parse_data->dbname.length))) + if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); if (check_db_dir_existence(parse_data->dbname.str)) @@ -432,10 +326,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE EVENT command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists))) @@ -473,18 +367,21 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, { sql_print_error("Event Error: An error occurred while creating query string, " "before writing it into binary log."); - /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; - DBUG_RETURN(TRUE); + ret= TRUE; + } + else + { + /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER + will be written into the binary log as the definer for the SQL thread. */ + ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); } - /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER - will be written into the binary log as the definer for the SQL thread. */ - ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); } } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } @@ -519,22 +416,13 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, DBUG_ENTER("Events::update_event"); - /* - For consistency, implicit COMMIT should be the first thing in the - execution chain. - */ - if (end_active_trans(thd)) - DBUG_RETURN(TRUE); - if (check_if_system_tables_error()) DBUG_RETURN(TRUE); if (parse_data->check_parse_data(thd) || parse_data->do_not_create) DBUG_RETURN(TRUE); - if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0, - is_schema_db(parse_data->dbname.str, - parse_data->dbname.length))) + if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); if (new_dbname) /* It's a rename */ @@ -555,8 +443,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, to tell the user that a database doesn't exist if they can not access it. */ - if (check_access(thd, EVENT_ACL, new_dbname->str, 0, 0, 0, - is_schema_db(new_dbname->str, new_dbname->length))) + if (check_access(thd, EVENT_ACL, new_dbname->str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); /* Check that the target database exists */ @@ -571,10 +458,10 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for UPDATE EVENT command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->update_event(thd, parse_data, @@ -607,9 +494,11 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } @@ -646,35 +535,20 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) bool save_binlog_row_based; DBUG_ENTER("Events::drop_event"); - /* - In MySQL, DDL must always commit: since mysql.* tables are - non-transactional, we must modify them outside a transaction - to not break atomicity. - But the second and more important reason to commit here - regardless whether we're actually changing mysql.event table - or not is replication: end_active_trans syncs the binary log, - and unless we run DDL in it's own transaction it may simply - never appear on the slave in case the outside transaction - rolls back. - */ - if (end_active_trans(thd)) - DBUG_RETURN(TRUE); - if (check_if_system_tables_error()) DBUG_RETURN(TRUE); - if (check_access(thd, EVENT_ACL, dbname.str, 0, 0, 0, - is_schema_db(dbname.str, dbname.length))) + if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); /* Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP EVENT command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row())) + thd->clear_current_stmt_binlog_format_row(); - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists))) { @@ -684,9 +558,11 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) DBUG_ASSERT(thd->query() && thd->query_length()); ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ - thd->current_stmt_binlog_row_based= save_binlog_row_based; + DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row()); + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(ret); } @@ -715,11 +591,11 @@ Events::drop_schema_events(THD *thd, char *db) are damaged, as intended. */ - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); if (event_queue) event_queue->drop_schema_events(thd, db_lex); db_repository->drop_schema_events(thd, db_lex); - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); DBUG_VOID_RETURN; } @@ -747,8 +623,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol) field_list.push_back(new Item_empty_string("Event", NAME_CHAR_LEN)); - if (sys_var_thd_sql_mode::symbolic_mode_representation(thd, et->sql_mode, - &sql_mode)) + if (sql_mode_string_representation(thd, et->sql_mode, &sql_mode)) DBUG_RETURN(TRUE); field_list.push_back(new Item_empty_string("sql_mode", (uint) sql_mode.length)); @@ -813,7 +688,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol) bool Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) { - Open_tables_state open_tables_backup; + Open_tables_backup open_tables_backup; Event_timed et; bool ret; @@ -823,8 +698,7 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) if (check_if_system_tables_error()) DBUG_RETURN(TRUE); - if (check_access(thd, EVENT_ACL, dbname.str, 0, 0, 0, - is_schema_db(dbname.str, dbname.length))) + if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); /* @@ -869,7 +743,7 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) { char *db= NULL; int ret; - Open_tables_state open_tables_backup; + Open_tables_backup open_tables_backup; DBUG_ENTER("Events::fill_schema_events"); if (check_if_system_tables_error()) @@ -882,8 +756,9 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { DBUG_ASSERT(thd->lex->select_lex.db); - if (!is_schema_db(thd->lex->select_lex.db) && // There is no events in I_S - check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 0)) + if (!is_infoschema_db(thd->lex->select_lex.db) && // There is no events in I_S + check_access(thd, EVENT_ACL, thd->lex->select_lex.db, + NULL, NULL, 0, 0)) DBUG_RETURN(1); db= thd->lex->select_lex.db; } @@ -938,7 +813,6 @@ Events::init(my_bool opt_noacl_or_bootstrap) */ thd->thread_stack= (char*) &thd; thd->store_globals(); - lex_start(thd); /* We will need Event_db_repository anyway, even if the scheduler is @@ -1044,6 +918,51 @@ Events::deinit() DBUG_VOID_RETURN; } +#ifdef HAVE_PSI_INTERFACE +PSI_mutex_key key_LOCK_event_metadata, key_LOCK_event_queue, + key_event_scheduler_LOCK_scheduler_state; + +static PSI_mutex_info all_events_mutexes[]= +{ + { &key_LOCK_event_metadata, "LOCK_event_metadata", PSI_FLAG_GLOBAL}, + { &key_LOCK_event_queue, "LOCK_event_queue", PSI_FLAG_GLOBAL}, + { &key_event_scheduler_LOCK_scheduler_state, "Event_scheduler::LOCK_scheduler_state", PSI_FLAG_GLOBAL} +}; + +PSI_cond_key key_event_scheduler_COND_state, key_COND_queue_state; + +static PSI_cond_info all_events_conds[]= +{ + { &key_event_scheduler_COND_state, "Event_scheduler::COND_state", PSI_FLAG_GLOBAL}, + { &key_COND_queue_state, "COND_queue_state", PSI_FLAG_GLOBAL}, +}; + +PSI_thread_key key_thread_event_scheduler, key_thread_event_worker; + +static PSI_thread_info all_events_threads[]= +{ + { &key_thread_event_scheduler, "event_scheduler", PSI_FLAG_GLOBAL}, + { &key_thread_event_worker, "event_worker", 0} +}; + +static void init_events_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_events_mutexes); + PSI_server->register_mutex(category, all_events_mutexes, count); + + count= array_elements(all_events_conds); + PSI_server->register_cond(category, all_events_conds, count); + + count= array_elements(all_events_threads); + PSI_server->register_thread(category, all_events_threads, count); +} +#endif /* HAVE_PSI_INTERFACE */ /** Inits Events mutexes @@ -1056,7 +975,12 @@ Events::deinit() void Events::init_mutexes() { - pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST); +#ifdef HAVE_PSI_INTERFACE + init_events_psi_keys(); +#endif + + mysql_mutex_init(key_LOCK_event_metadata, + &LOCK_event_metadata, MY_MUTEX_INIT_FAST); } @@ -1070,7 +994,7 @@ Events::init_mutexes() void Events::destroy_mutexes() { - pthread_mutex_destroy(&LOCK_event_metadata); + mysql_mutex_destroy(&LOCK_event_metadata); } @@ -1092,7 +1016,11 @@ Events::dump_internal_status() puts("LLA = Last Locked At LUA = Last Unlocked At"); puts("WOC = Waiting On Condition DL = Data Locked"); - pthread_mutex_lock(&LOCK_event_metadata); + /* + opt_event_scheduler should only be accessed while + holding LOCK_global_system_variables. + */ + mysql_mutex_lock(&LOCK_global_system_variables); if (opt_event_scheduler == EVENTS_DISABLED) puts("The Event Scheduler is disabled"); else @@ -1101,64 +1029,19 @@ Events::dump_internal_status() event_queue->dump_internal_status(); } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_global_system_variables); DBUG_VOID_RETURN; } - -/** - Starts or stops the event scheduler thread. - - @retval FALSE success - @retval TRUE error -*/ - -bool -Events::switch_event_scheduler_state(enum_opt_event_scheduler new_state) +bool Events::start() { - bool ret= FALSE; - - DBUG_ENTER("Events::switch_event_scheduler_state"); - - DBUG_ASSERT(new_state == Events::EVENTS_ON || - new_state == Events::EVENTS_OFF); - - /* - If the scheduler was disabled because there are no/bad - system tables, produce a more meaningful error message - than ER_OPTION_PREVENTS_STATEMENT - */ - if (check_if_system_tables_error()) - DBUG_RETURN(TRUE); - - pthread_mutex_lock(&LOCK_event_metadata); - - if (opt_event_scheduler == EVENTS_DISABLED) - { - my_error(ER_OPTION_PREVENTS_STATEMENT, - MYF(0), "--event-scheduler=DISABLED or --skip-grant-tables"); - ret= TRUE; - goto end; - } - - if (new_state == EVENTS_ON) - ret= scheduler->start(); - else - ret= scheduler->stop(); - - if (ret) - { - my_error(ER_EVENT_SET_VAR_ERROR, MYF(0)); - goto end; - } - - opt_event_scheduler= new_state; - -end: - pthread_mutex_unlock(&LOCK_event_metadata); - DBUG_RETURN(ret); + return scheduler->start(); } +bool Events::stop() +{ + return scheduler->stop(); +} /** Loads all ENABLED events from mysql.event into a prioritized |