Commit 70856a0d authored by unknown's avatar unknown

WL#1034

updated sources


sql/event.cc:
  update
  put some error calls to the places they occur
sql/event.h:
  - change the default (does not work in STRICT mode)
sql/event_executor.cc:
  move mutex initialization to evex_init_mutexes so init_events() can be reused when the
  main thread does not work and set global event_scheduler=1; (this will start the thread)
  The main thread is now visible with show processlist and can be killed.
sql/event_priv.h:
  don't use anymore SP for opening table
sql/event_timed.cc:
  don't use anymore SP routines for opening mysql.event
sql/mysqld.cc:
  shutdown_events() should be maximal at the end of the server because
  it destroys mutexes of EVEX. The call should not be in the main thread.
sql/set_var.cc:
  make sys_var_event_executor subclass sys_var_bool_ptr
  to overload ::update() method - needed to start a
  killed (non-running) evex main thread
sql/set_var.h:
  declare class sys_var_event_executor
sql/share/errmsg.txt:
  2 new messages
parent 7ff79771
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
/* /*
TODO list : TODO list :
- The default value of created/modified should not be 0000-00-00 because of
STRICT mode restricions.
- Remove m_ prefixes of member variables. - Remove m_ prefixes of member variables.
- Use timestamps instead of datetime. - Use timestamps instead of datetime.
...@@ -150,6 +152,93 @@ event_timed_compare(event_timed **a, event_timed **b) ...@@ -150,6 +152,93 @@ event_timed_compare(event_timed **a, event_timed **b)
} }
/*
Open mysql.event table for read
SYNOPSIS
evex_open_event_table_for_read()
thd Thread context
lock_type How to lock the table
RETURN
0 Error
# Pointer to TABLE object
*/
TABLE *evex_open_event_table(THD *thd, enum thr_lock_type lock_type)
{
TABLE_LIST tables;
bool not_used;
DBUG_ENTER("open_proc_table");
/*
Speed up things if the table doesn't exists. *table_exists
is set when we create or read stored procedure or on flush privileges.
*/
if (!mysql_event_table_exists)
DBUG_RETURN(0);
bzero((char*) &tables, sizeof(tables));
tables.db= (char*) "mysql";
tables.table_name= tables.alias= (char*) "event";
tables.lock_type= lock_type;
if (simple_open_n_lock_tables(thd, &tables))
{
mysql_event_table_exists= 0;
DBUG_RETURN(0);
}
DBUG_RETURN(tables.table);
}
/*
Find row in open mysql.event table representing event
SYNOPSIS
evex_db_find_routine_aux()
thd Thread context
dbname Name of event's database
rname Name of the event inside the db
table TABLE object for open mysql.event table.
RETURN VALUE
SP_OK - Routine found
SP_KEY_NOT_FOUND- No routine with given name
*/
static int
evex_db_find_routine_aux(THD *thd, const LEX_STRING dbname,
const LEX_STRING rname, TABLE *table)
{
byte key[MAX_KEY_LENGTH]; // db, name, optional key length type
DBUG_ENTER("evex_db_find_routine_aux");
DBUG_PRINT("enter", ("name: %.*s", rname.length, rname.str));
/*
Create key to find row. We have to use field->store() to be able to
handle VARCHAR and CHAR fields.
Assumption here is that the two first fields in the table are
'db' and 'name' and the first key is the primary key over the
same fields.
*/
if (rname.length > table->field[1]->field_length)
DBUG_RETURN(SP_KEY_NOT_FOUND);
table->field[0]->store(dbname.str, dbname.length, &my_charset_bin);
table->field[1]->store(rname.str, rname.length, &my_charset_bin);
key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
if (table->file->index_read_idx(table->record[0], 0,
key, table->key_info->key_length,
HA_READ_KEY_EXACT))
DBUG_RETURN(SP_KEY_NOT_FOUND);
DBUG_RETURN(0);
}
/* /*
Puts some data common to CREATE and ALTER EVENT into a row. Puts some data common to CREATE and ALTER EVENT into a row.
...@@ -164,13 +253,13 @@ event_timed_compare(event_timed **a, event_timed **b) ...@@ -164,13 +253,13 @@ event_timed_compare(event_timed **a, event_timed **b)
*/ */
static int static int
evex_fill_row(THD *thd, TABLE *table, event_timed *et) evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
{ {
DBUG_ENTER("evex_fill_row"); DBUG_ENTER("evex_fill_row");
int ret=0; int ret=0;
if (table->s->fields != EVEX_FIELD_COUNT) if (table->s->fields != EVEX_FIELD_COUNT)
goto get_field_failed; DBUG_RETURN(EVEX_GET_FIELD_FAILED);
DBUG_PRINT("info", ("m_db.len=%d",et->m_db.length)); DBUG_PRINT("info", ("m_db.len=%d",et->m_db.length));
DBUG_PRINT("info", ("m_name.len=%d",et->m_name.length)); DBUG_PRINT("info", ("m_name.len=%d",et->m_name.length));
...@@ -195,13 +284,13 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et) ...@@ -195,13 +284,13 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et)
if (et->m_starts.year) if (et->m_starts.year)
{ {
table->field[EVEX_FIELD_STARTS]->set_notnull();// set NULL flag to OFF table->field[EVEX_FIELD_STARTS]->set_notnull();// set NULL flag to OFF
table->field[EVEX_FIELD_STARTS]->store_time(&et->m_starts,MYSQL_TIMESTAMP_DATETIME); table->field[EVEX_FIELD_STARTS]->store_time(&et->m_starts,MYSQL_TIMESTAMP_DATETIME);
} }
if (et->m_ends.year) if (et->m_ends.year)
{ {
table->field[EVEX_FIELD_ENDS]->set_notnull(); table->field[EVEX_FIELD_ENDS]->set_notnull();
table->field[EVEX_FIELD_ENDS]->store_time(&et->m_ends, MYSQL_TIMESTAMP_DATETIME); table->field[EVEX_FIELD_ENDS]->store_time(&et->m_ends, MYSQL_TIMESTAMP_DATETIME);
} }
if (et->m_expr) if (et->m_expr)
...@@ -220,13 +309,15 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et) ...@@ -220,13 +309,15 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et)
{ {
// fix_fields already called in init_execute_at // fix_fields already called in init_execute_at
table->field[EVEX_FIELD_EXECUTE_AT]->set_notnull(); table->field[EVEX_FIELD_EXECUTE_AT]->set_notnull();
table->field[EVEX_FIELD_EXECUTE_AT]->store_time(&et->m_execute_at, MYSQL_TIMESTAMP_DATETIME); table->field[EVEX_FIELD_EXECUTE_AT]->store_time(&et->m_execute_at,
MYSQL_TIMESTAMP_DATETIME);
//this will make it NULL because we don't call set_notnull //this will make it NULL because we don't call set_notnull
table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->store((longlong) 0); table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->store((longlong) 0);
} }
else else
{ {
DBUG_ASSERT(is_update);
// it is normal to be here when the action is update // it is normal to be here when the action is update
// this is an error if the action is create. something is borked // this is an error if the action is create. something is borked
} }
...@@ -238,8 +329,6 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et) ...@@ -238,8 +329,6 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et)
store((et->m_comment).str, (et->m_comment).length, system_charset_info); store((et->m_comment).str, (et->m_comment).length, system_charset_info);
DBUG_RETURN(0); DBUG_RETURN(0);
get_field_failed:
DBUG_RETURN(EVEX_GET_FIELD_FAILED);
} }
...@@ -259,34 +348,38 @@ get_field_failed: ...@@ -259,34 +348,38 @@ get_field_failed:
static int static int
db_create_event(THD *thd, event_timed *et) db_create_event(THD *thd, event_timed *et)
{ {
int ret; int ret= EVEX_OK;
TABLE *table; TABLE *table;
TABLE_LIST tables;
char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
char olddb[128]; char olddb[128];
bool dbchanged; bool dbchanged= false;
DBUG_ENTER("db_create_event"); DBUG_ENTER("db_create_event");
DBUG_PRINT("enter", ("name: %.*s", et->m_name.length, et->m_name.str)); DBUG_PRINT("enter", ("name: %.*s", et->m_name.length, et->m_name.str));
dbchanged= false;
if ((ret= sp_use_new_db(thd, et->m_db.str, olddb, sizeof(olddb), DBUG_PRINT("info", ("open mysql.event for update"));
0, &dbchanged))) if (!(table= evex_open_event_table(thd, TL_WRITE)))
{ {
DBUG_PRINT("info", ("cannot use_new_db. code=%d", ret)); my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
DBUG_RETURN(EVEX_NO_DB_ERROR); goto done;
} }
bzero(&tables, sizeof(tables)); DBUG_PRINT("info", ("check existance of an event with the same name"));
tables.db= (char*)"mysql"; if (!evex_db_find_routine_aux(thd, et->m_db, et->m_name, table))
tables.table_name= tables.alias= (char*)"event";
if (!(table= EVEX_OPEN_TABLE_FOR_UPDATE()))
{ {
if (dbchanged) my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), et->m_name.str);
(void)mysql_change_db(thd, olddb, 1); goto done;
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
} }
DBUG_PRINT("info", ("non-existant, go forward"));
if ((ret= sp_use_new_db(thd, et->m_db.str, olddb, sizeof(olddb),
0, &dbchanged)))
{
DBUG_PRINT("info", ("cannot use_new_db. code=%d", ret));
my_error(ER_BAD_DB_ERROR, MYF(0));
DBUG_RETURN(0);
}
restore_record(table, s->default_values); // Get default values for fields restore_record(table, s->default_values); // Get default values for fields
strxmov(definer, et->m_definer_user.str, "@", et->m_definer_host.str, NullS); strxmov(definer, et->m_definer_user.str, "@", et->m_definer_host.str, NullS);
...@@ -305,25 +398,25 @@ db_create_event(THD *thd, event_timed *et) ...@@ -305,25 +398,25 @@ db_create_event(THD *thd, event_timed *et)
*/ */
if (!(et->m_expr) && !(et->m_execute_at.year)) if (!(et->m_expr) && !(et->m_execute_at.year))
{ {
DBUG_PRINT("error", ("neither m_expr nor m_execute_as is set!")); DBUG_PRINT("error", ("neither m_expr nor m_execute_as are set!"));
ret= EVEX_WRITE_ROW_FAILED; my_error(ER_EVENT_NEITHER_M_EXPR_NOR_M_AT, MYF(0));
goto done; goto done;
} }
ret= table->field[EVEX_FIELD_DEFINER]->
store(definer, (uint)strlen(definer), system_charset_info); if (table->field[EVEX_FIELD_DEFINER]->
if (ret) store(definer, (uint)strlen(definer), system_charset_info))
{ {
ret= EVEX_PARSE_ERROR; my_error(ER_EVENT_STORE_FAILED, MYF(0), et->m_name.str);
goto done; goto done;
} }
((Field_timestamp *)table->field[EVEX_FIELD_CREATED])->set_time(); ((Field_timestamp *)table->field[EVEX_FIELD_CREATED])->set_time();
if ((ret= evex_fill_row(thd, table, et))) if ((ret= evex_fill_row(thd, table, et, false)))
goto done; goto done;
ret= EVEX_OK; ret= EVEX_OK;
if (table->file->write_row(table->record[0])) if (table->file->write_row(table->record[0]))
ret= EVEX_WRITE_ROW_FAILED; my_error(ER_EVENT_STORE_FAILED, MYF(0), et->m_name.str);
else if (mysql_bin_log.is_open()) else if (mysql_bin_log.is_open())
{ {
thd->clear_error(); thd->clear_error();
...@@ -333,9 +426,10 @@ db_create_event(THD *thd, event_timed *et) ...@@ -333,9 +426,10 @@ db_create_event(THD *thd, event_timed *et)
} }
done: done:
close_thread_tables(thd); // No need to close the table, it will be closed in sql_parse::do_command
if (dbchanged) if (dbchanged)
(void)mysql_change_db(thd, olddb, 1); (void) mysql_change_db(thd, olddb, 1);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -365,34 +459,43 @@ db_update_event(THD *thd, sp_name *name, event_timed *et) ...@@ -365,34 +459,43 @@ db_update_event(THD *thd, sp_name *name, event_timed *et)
DBUG_PRINT("enter", ("rename to: %.*s", name->m_name.length, name->m_name.str)); DBUG_PRINT("enter", ("rename to: %.*s", name->m_name.length, name->m_name.str));
// Todo: Handle in sql_prepare.cc SP_OPEN_TABLE_FAILED // Todo: Handle in sql_prepare.cc SP_OPEN_TABLE_FAILED
if (!(table= EVEX_OPEN_TABLE_FOR_UPDATE())) if (!(table= evex_open_event_table(thd, TL_WRITE)))
DBUG_RETURN(SP_OPEN_TABLE_FAILED); {
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
goto done;
}
ret= sp_db_find_routine_aux(thd, 0/*notype*/, et->m_db, et->m_name, table); if (evex_db_find_routine_aux(thd, et->m_db, et->m_name, table) == SP_KEY_NOT_FOUND)
if (ret == EVEX_OK)
{ {
store_record(table,record[1]); my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->m_name.str);
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; // Don't update create on row update. goto done;
ret= evex_fill_row(thd, table, et); }
if (ret)
goto done; store_record(table,record[1]);
if (name) table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; // Don't update create on row update.
{ if ((ret= evex_fill_row(thd, table, et, true)))
table->field[EVEX_FIELD_DB]-> goto done;
store(name->m_db.str, name->m_db.length, system_charset_info);
table->field[EVEX_FIELD_NAME]-> if (name)
store(name->m_name.str, name->m_name.length, system_charset_info); {
} table->field[EVEX_FIELD_DB]->
store(name->m_db.str, name->m_db.length, system_charset_info);
table->field[EVEX_FIELD_NAME]->
store(name->m_name.str, name->m_name.length, system_charset_info);
}
if ((table->file->update_row(table->record[1],table->record[0]))) if ((ret= table->file->update_row(table->record[1],table->record[0])))
ret= EVEX_WRITE_ROW_FAILED; {
my_error(ER_EVENT_STORE_FAILED, MYF(0), et->m_name.str);
goto done;
} }
done: done:
close_thread_tables(thd); close_thread_tables(thd);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
/* /*
Use sp_name for look up, return in **ett if found Use sp_name for look up, return in **ett if found
*/ */
...@@ -404,18 +507,18 @@ db_find_event(THD *thd, sp_name *name, event_timed **ett) ...@@ -404,18 +507,18 @@ db_find_event(THD *thd, sp_name *name, event_timed **ett)
const char *definer; const char *definer;
char *ptr; char *ptr;
event_timed *et; event_timed *et;
Open_tables_state open_tables_state_backup;
DBUG_ENTER("db_find_event"); DBUG_ENTER("db_find_event");
DBUG_PRINT("enter", ("name: %*s", DBUG_PRINT("enter", ("name: %*s",
name->m_name.length, name->m_name.str)); name->m_name.length, name->m_name.str));
if (!(table= open_proc_type_table_for_read(thd, &open_tables_state_backup, if (!(table= evex_open_event_table(thd, TL_READ)))
"event", &mysql_event_table_exists))) {
DBUG_RETURN(SP_OPEN_TABLE_FAILED); my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
goto done;
}
if ((ret= sp_db_find_routine_aux(thd, 0/*notype*/, name->m_db, name->m_name, if ((ret= evex_db_find_routine_aux(thd, name->m_db, name->m_name, table)))
table)) != SP_OK)
goto done; goto done;
et= new event_timed; et= new event_timed;
...@@ -434,7 +537,6 @@ done: ...@@ -434,7 +537,6 @@ done:
et= 0; et= 0;
} }
close_thread_tables(thd); close_thread_tables(thd);
thd->restore_backup_open_tables_state(&open_tables_state_backup);
*ett= et; *ett= et;
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -503,8 +605,6 @@ done: ...@@ -503,8 +605,6 @@ done:
if (thd->mem_root != tmp_mem_root) if (thd->mem_root != tmp_mem_root)
thd->mem_root= tmp_mem_root; thd->mem_root= tmp_mem_root;
if (spn)
delete spn;
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -619,19 +719,19 @@ int ...@@ -619,19 +719,19 @@ int
evex_create_event(THD *thd, event_timed *et, uint create_options) evex_create_event(THD *thd, event_timed *et, uint create_options)
{ {
int ret = 0; int ret = 0;
sp_name *spn= 0;
DBUG_ENTER("evex_create_event"); DBUG_ENTER("evex_create_event");
DBUG_PRINT("enter", ("name: %*s options:%d", et->m_name.length, DBUG_PRINT("enter", ("name: %*s options:%d", et->m_name.length,
et->m_name.str, create_options)); et->m_name.str, create_options));
/*
VOID(pthread_mutex_lock(&LOCK_evex_running)); VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running) if (!evex_is_running)
// TODO: put an warning to the user here. // TODO: put an warning to the user here.
// Is it needed? (Andrey, 051129) // Is it needed? (Andrey, 051129)
{} {}
VOID(pthread_mutex_unlock(&LOCK_evex_running)); VOID(pthread_mutex_unlock(&LOCK_evex_running));
*/
if ((ret = db_create_event(thd, et)) == EVEX_WRITE_ROW_FAILED && if ((ret = db_create_event(thd, et)) == EVEX_WRITE_ROW_FAILED &&
(create_options & HA_LEX_CREATE_IF_NOT_EXISTS)) (create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
...@@ -652,24 +752,16 @@ evex_create_event(THD *thd, event_timed *et, uint create_options) ...@@ -652,24 +752,16 @@ evex_create_event(THD *thd, event_timed *et, uint create_options)
goto done; goto done;
VOID(pthread_mutex_lock(&LOCK_evex_running)); VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running) if (evex_is_running && et->m_status == MYSQL_EVENT_ENABLED)
{ {
VOID(pthread_mutex_unlock(&LOCK_evex_running)); sp_name spn(et->m_db, et->m_name);
goto done; ret= evex_load_and_compile_event(thd, &spn, true);
}
VOID(pthread_mutex_unlock(&LOCK_evex_running));
//cache only if the event is ENABLED
if (et->m_status == MYSQL_EVENT_ENABLED)
{
spn= new sp_name(et->m_db, et->m_name);
if ((ret= evex_load_and_compile_event(thd, spn, true)))
goto done;
} }
VOID(pthread_mutex_unlock(&LOCK_evex_running));
done: done:
if (spn) // No need to close the table, it will be closed in sql_parse::do_command
delete spn;
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -685,7 +777,7 @@ done: ...@@ -685,7 +777,7 @@ done:
NOTES NOTES
et contains data about dbname and event name. et contains data about dbname and event name.
name is the new name of the event. if not null this means name is the new name of the event, if not null this means
that RENAME TO was specified in the query. that RENAME TO was specified in the query.
TODO TODO
- Add code for in-memory structures - caching & uncaching. - Add code for in-memory structures - caching & uncaching.
...@@ -701,19 +793,24 @@ evex_update_event(THD *thd, sp_name *name, event_timed *et) ...@@ -701,19 +793,24 @@ evex_update_event(THD *thd, sp_name *name, event_timed *et)
DBUG_ENTER("evex_update_event"); DBUG_ENTER("evex_update_event");
DBUG_PRINT("enter", ("name: %*s", et->m_name.length, et->m_name.str)); DBUG_PRINT("enter", ("name: %*s", et->m_name.length, et->m_name.str));
/*
VOID(pthread_mutex_lock(&LOCK_evex_running)); VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running) if (!evex_is_running)
// put an warning to the user here // put an warning to the user here
{} {}
VOID(pthread_mutex_unlock(&LOCK_evex_running)); VOID(pthread_mutex_unlock(&LOCK_evex_running));
*/
if ((ret= db_update_event(thd, name, et))) if ((ret= db_update_event(thd, name, et)))
goto done_no_evex; goto done_no_evex;
VOID(pthread_mutex_lock(&LOCK_evex_running)); VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running) if (!evex_is_running)
// not running - therefore no memory structures {
// not running - therefore no memory structures
VOID(pthread_mutex_unlock(&LOCK_evex_running));
goto done_no_evex; goto done_no_evex;
}
VOID(pthread_mutex_unlock(&LOCK_evex_running)); VOID(pthread_mutex_unlock(&LOCK_evex_running));
/* /*
...@@ -721,31 +818,23 @@ evex_update_event(THD *thd, sp_name *name, event_timed *et) ...@@ -721,31 +818,23 @@ evex_update_event(THD *thd, sp_name *name, event_timed *et)
The reason is that DISABLED events are not cached. The reason is that DISABLED events are not cached.
*/ */
VOID(pthread_mutex_lock(&LOCK_event_arrays)); VOID(pthread_mutex_lock(&LOCK_event_arrays));
if (name) evex_remove_from_cache(&et->m_db, &et->m_name, false);
{ if (et->m_status == MYSQL_EVENT_ENABLED)
evex_remove_from_cache(&name->m_db, &name->m_name, false); if (name)
if (et->m_status == MYSQL_EVENT_ENABLED && ret= evex_load_and_compile_event(thd, name, false);
(ret= evex_load_and_compile_event(thd, name, false)) else
)
goto done;
}
else
{
evex_remove_from_cache(&et->m_db, &et->m_name, false);
spn= new sp_name(et->m_db, et->m_name);
if (et->m_status == MYSQL_EVENT_ENABLED &&
(ret= evex_load_and_compile_event(thd, spn, false))
)
{ {
spn= new sp_name(et->m_db, et->m_name);
ret= evex_load_and_compile_event(thd, spn, false);
delete spn; delete spn;
goto done; }
}
}
done: done:
VOID(pthread_mutex_unlock(&LOCK_event_arrays)); VOID(pthread_mutex_unlock(&LOCK_event_arrays));
done_no_evex: done_no_evex:
// No need to close the table, it will be closed in sql_parse::do_command
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -771,13 +860,15 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists) ...@@ -771,13 +860,15 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists)
bool opened; bool opened;
DBUG_ENTER("evex_drop_event"); DBUG_ENTER("evex_drop_event");
/*
VOID(pthread_mutex_lock(&LOCK_evex_running)); VOID(pthread_mutex_lock(&LOCK_evex_running));
if (!evex_is_running) if (!evex_is_running)
// put an warning to the user here // put an warning to the user here
{} {}
VOID(pthread_mutex_unlock(&LOCK_evex_running)); VOID(pthread_mutex_unlock(&LOCK_evex_running));
*/
if (!(table= EVEX_OPEN_TABLE_FOR_UPDATE())) ////
if (!(table= evex_open_event_table(thd, TL_WRITE)))
DBUG_RETURN(SP_OPEN_TABLE_FAILED); DBUG_RETURN(SP_OPEN_TABLE_FAILED);
ret= sp_db_find_routine_aux(thd, 0/*notype*/, et->m_db, et->m_name, table); ret= sp_db_find_routine_aux(thd, 0/*notype*/, et->m_db, et->m_name, table);
...@@ -806,14 +897,8 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists) ...@@ -806,14 +897,8 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists)
VOID(pthread_mutex_unlock(&LOCK_evex_running)); VOID(pthread_mutex_unlock(&LOCK_evex_running));
done: done:
/* // No need to close the table, it will be closed in sql_parse::do_command
"opened" is switched to TRUE when we open mysql.event for checking.
In this case we have to close the table after finishing working with it.
*/
close_thread_tables(thd);
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -214,8 +214,8 @@ CREATE TABLE `event` ( ...@@ -214,8 +214,8 @@ CREATE TABLE `event` (
`execute_at` datetime default NULL, `execute_at` datetime default NULL,
`transient_expression` int(11) default NULL, `transient_expression` int(11) default NULL,
`interval_type` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, `interval_type` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL,
`created` timestamp NOT NULL default '0000-00-00 00:00:00', `created` timestamp NOT NULL,
`modified` timestamp NOT NULL default '0000-00-00 00:00:00', `modified` timestamp NOT NULL,
`last_executed` datetime default NULL, `last_executed` datetime default NULL,
`starts` datetime default NULL, `starts` datetime default NULL,
`ends` datetime default NULL, `ends` datetime default NULL,
......
...@@ -36,6 +36,7 @@ my_bool event_executor_running_global_var= false; ...@@ -36,6 +36,7 @@ my_bool event_executor_running_global_var= false;
extern ulong thread_created; extern ulong thread_created;
static my_bool evex_mutexes_initted= false;
static int static int
evex_load_events_from_db(THD *thd); evex_load_events_from_db(THD *thd);
...@@ -50,6 +51,19 @@ evex_load_events_from_db(THD *thd); ...@@ -50,6 +51,19 @@ evex_load_events_from_db(THD *thd);
pthread_handler_t event_executor_worker(void *arg); pthread_handler_t event_executor_worker(void *arg);
pthread_handler_t event_executor_main(void *arg); pthread_handler_t event_executor_main(void *arg);
static
void evex_init_mutexes()
{
if (evex_mutexes_initted)
{
evex_mutexes_initted= true;
return;
}
pthread_mutex_init(&LOCK_event_arrays, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&LOCK_workers_count, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&LOCK_evex_running, MY_MUTEX_INIT_FAST);
}
int int
init_events() init_events()
{ {
...@@ -59,15 +73,15 @@ init_events() ...@@ -59,15 +73,15 @@ init_events()
DBUG_PRINT("info",("Starting events main thread")); DBUG_PRINT("info",("Starting events main thread"));
pthread_mutex_init(&LOCK_event_arrays, MY_MUTEX_INIT_FAST); evex_init_mutexes();
pthread_mutex_init(&LOCK_workers_count, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&LOCK_evex_running, MY_MUTEX_INIT_FAST);
VOID(pthread_mutex_lock(&LOCK_evex_running)); VOID(pthread_mutex_lock(&LOCK_evex_running));
evex_is_running= false; evex_is_running= false;
event_executor_running_global_var= false; event_executor_running_global_var= false;
VOID(pthread_mutex_unlock(&LOCK_evex_running)); VOID(pthread_mutex_unlock(&LOCK_evex_running));
DBUG_RETURN(0);
/*
#ifndef DBUG_FAULTY_THR #ifndef DBUG_FAULTY_THR
//TODO Andrey: Change the error code returned! //TODO Andrey: Change the error code returned!
if (pthread_create(&th, NULL, event_executor_main, (void*)NULL)) if (pthread_create(&th, NULL, event_executor_main, (void*)NULL))
...@@ -77,6 +91,7 @@ init_events() ...@@ -77,6 +91,7 @@ init_events()
#endif #endif
DBUG_RETURN(0); DBUG_RETURN(0);
*/
} }
...@@ -94,6 +109,7 @@ shutdown_events() ...@@ -94,6 +109,7 @@ shutdown_events()
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#ifdef ANDREY_0
static int static int
init_event_thread(THD* thd) init_event_thread(THD* thd)
...@@ -165,7 +181,7 @@ pthread_handler_t event_executor_main(void *arg) ...@@ -165,7 +181,7 @@ pthread_handler_t event_executor_main(void *arg)
goto err; goto err;
// make this thread invisible it has no vio -> show processlist won't see // make this thread invisible it has no vio -> show processlist won't see
thd->system_thread= 0; thd->system_thread= 1;
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
threads.append(thd); threads.append(thd);
...@@ -350,7 +366,7 @@ err_no_thd: ...@@ -350,7 +366,7 @@ err_no_thd:
free_root(&evex_mem_root, MYF(0)); free_root(&evex_mem_root, MYF(0));
sql_print_information("Event executor stopped"); sql_print_information("Event executor stopped");
shutdown_events(); // shutdown_events();
my_thread_end(); my_thread_end();
pthread_exit(0); pthread_exit(0);
...@@ -391,7 +407,7 @@ pthread_handler_t event_executor_worker(void *event_void) ...@@ -391,7 +407,7 @@ pthread_handler_t event_executor_worker(void *event_void)
thd->init_for_queries(); thd->init_for_queries();
// make this thread visible it has no vio -> show processlist needs this flag // make this thread visible it has no vio -> show processlist needs this flag
thd->system_thread= 0; thd->system_thread= 1;
VOID(pthread_mutex_lock(&LOCK_thread_count)); VOID(pthread_mutex_lock(&LOCK_thread_count));
threads.append(thd); threads.append(thd);
...@@ -531,3 +547,20 @@ end: ...@@ -531,3 +547,20 @@ end:
("Events loaded from DB. Status code %d", ret)); ("Events loaded from DB. Status code %d", ret));
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
#endif
bool sys_var_event_executor::update(THD *thd, set_var *var)
{
#ifdef ANDREY_0
// here start the thread if not running.
VOID(pthread_mutex_lock(&LOCK_evex_running));
if ((my_bool) var->save_result.ulong_value && !evex_is_running) {
VOID(pthread_mutex_unlock(&LOCK_evex_running));
init_events();
} else
VOID(pthread_mutex_unlock(&LOCK_evex_running));
#endif
return sys_var_bool_ptr::update(thd, var);
}
...@@ -17,9 +17,6 @@ ...@@ -17,9 +17,6 @@
#ifndef _EVENT_PRIV_H_ #ifndef _EVENT_PRIV_H_
#define _EVENT_PRIV_H_ #define _EVENT_PRIV_H_
#define EVEX_OPEN_TABLE_FOR_UPDATE() \
open_proc_type_table_for_update(thd, "event", &mysql_event_table_exists)
enum enum
{ {
...@@ -53,5 +50,7 @@ extern pthread_mutex_t LOCK_event_arrays, ...@@ -53,5 +50,7 @@ extern pthread_mutex_t LOCK_event_arrays,
int int
my_time_compare(TIME *a, TIME *b); my_time_compare(TIME *a, TIME *b);
TABLE *evex_open_event_table(THD *thd, enum thr_lock_type lock_type);
#endif /* _EVENT_PRIV_H_ */ #endif /* _EVENT_PRIV_H_ */
...@@ -719,7 +719,7 @@ event_timed::update_fields(THD *thd) ...@@ -719,7 +719,7 @@ event_timed::update_fields(THD *thd)
if (!(m_status_changed || m_last_executed_changed)) if (!(m_status_changed || m_last_executed_changed))
goto done; goto done;
if (!(table= EVEX_OPEN_TABLE_FOR_UPDATE())) if (!(table= evex_open_event_table(thd, TL_WRITE)))
DBUG_RETURN(SP_OPEN_TABLE_FAILED); DBUG_RETURN(SP_OPEN_TABLE_FAILED);
if ((ret= sp_db_find_routine_aux(thd, 0/*notype*/, m_db, m_name, table))) if ((ret= sp_db_find_routine_aux(thd, 0/*notype*/, m_db, m_name, table)))
......
...@@ -3568,6 +3568,7 @@ we force server id to 2, but this MySQL server will not act as a slave."); ...@@ -3568,6 +3568,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
clean_up(1); clean_up(1);
wait_for_signal_thread_to_end(); wait_for_signal_thread_to_end();
clean_up_mutexes(); clean_up_mutexes();
shutdown_events();
my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
exit(0); exit(0);
......
...@@ -207,7 +207,7 @@ sys_var_long_ptr sys_delayed_insert_timeout("delayed_insert_timeout", ...@@ -207,7 +207,7 @@ sys_var_long_ptr sys_delayed_insert_timeout("delayed_insert_timeout",
&delayed_insert_timeout); &delayed_insert_timeout);
sys_var_long_ptr sys_delayed_queue_size("delayed_queue_size", sys_var_long_ptr sys_delayed_queue_size("delayed_queue_size",
&delayed_queue_size); &delayed_queue_size);
sys_var_bool_ptr sys_event_executor("event_scheduler", sys_var_event_executor sys_event_executor("event_scheduler",
&event_executor_running_global_var); &event_executor_running_global_var);
sys_var_long_ptr sys_expire_logs_days("expire_logs_days", sys_var_long_ptr sys_expire_logs_days("expire_logs_days",
&expire_logs_days); &expire_logs_days);
...@@ -3364,6 +3364,7 @@ bool sys_var_trust_routine_creators::update(THD *thd, set_var *var) ...@@ -3364,6 +3364,7 @@ bool sys_var_trust_routine_creators::update(THD *thd, set_var *var)
return sys_var_bool_ptr::update(thd, var); return sys_var_bool_ptr::update(thd, var);
} }
/**************************************************************************** /****************************************************************************
Used templates Used templates
****************************************************************************/ ****************************************************************************/
......
...@@ -782,6 +782,17 @@ public: ...@@ -782,6 +782,17 @@ public:
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
}; };
class sys_var_event_executor :public sys_var_bool_ptr
{
/* We need a derived class only to have a warn_deprecated() */
public:
sys_var_event_executor(const char *name_arg, my_bool *value_arg) :
sys_var_bool_ptr(name_arg, value_arg) {};
bool update(THD *thd, set_var *var);
};
/**************************************************************************** /****************************************************************************
Classes for parsing of the SET command Classes for parsing of the SET command
****************************************************************************/ ****************************************************************************/
......
...@@ -5737,3 +5737,7 @@ ER_EVENT_ENDS_BEFORE_STARTS ...@@ -5737,3 +5737,7 @@ ER_EVENT_ENDS_BEFORE_STARTS
eng "ENDS must be after STARTS" eng "ENDS must be after STARTS"
ER_EVENT_EXEC_TIME_IN_THE_PAST ER_EVENT_EXEC_TIME_IN_THE_PAST
eng "Activation (AT) time is in the past" eng "Activation (AT) time is in the past"
ER_EVENT_OPEN_TABLE_FAILED
eng "Failed to open mysql.event"
ER_EVENT_NEITHER_M_EXPR_NOR_M_AT
eng "No datetime expression provided"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment