summaryrefslogtreecommitdiff
path: root/sql/events.cc
diff options
context:
space:
mode:
authorAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-03-24 18:03:44 +0300
committerAlexey Kopytov <Alexey.Kopytov@Sun.com>2010-03-24 18:03:44 +0300
commitd95c1e3b470506c7df6dfce3fe6dc7e5b46930ee (patch)
tree9f13d4fcc3ac732dc94fe2cae446f6f8c2b4e02b /sql/events.cc
parentabc6846d5b1df4846c4ffc03f4c93c82f874dd96 (diff)
parentae715642f46d4ed9ea8b5dd9b5cc9f3cace7f437 (diff)
downloadmariadb-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.cc337
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