diff options
-rw-r--r-- | mysql-test/r/events.result | 76 | ||||
-rw-r--r-- | mysql-test/t/events.test | 109 | ||||
-rw-r--r-- | sql/event.cc | 69 | ||||
-rw-r--r-- | sql/event_priv.h | 3 | ||||
-rw-r--r-- | sql/event_timed.cc | 14 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 |
6 files changed, 197 insertions, 76 deletions
diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index 41f944ab089..6048dbd3012 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -15,20 +15,11 @@ create event event2 on schedule every 2 second starts now() ends date_add(now(), drop event event2; create event e_43 on schedule every 1 second do set @a = 5; set global event_scheduler = 1; -select sleep(2); -sleep(2) -0 alter event e_43 do alter event e_43 do set @a = 4; -select sleep(3); -sleep(3) -0 select db, name, body, status, interval_field, interval_value from mysql.event; db name body status interval_field interval_value events_test e_43 set @a = 4 ENABLED SECOND 1 drop event e_43; -select sleep(1); -sleep(1) -0 set global event_scheduler = 0; create table t_event3 (a int, b float); drop event if exists event3; @@ -121,6 +112,7 @@ drop event two_event; drop event three_event; drop user ev_test@localhost; drop event one_event; +"Sleep a bit so the server closes the second connection" create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion @@ -137,4 +129,70 @@ set event_scheduler=0; ERROR HY000: Variable 'event_scheduler' is a GLOBAL variable and should be set with SET GLOBAL set global event_scheduler=2; ERROR 42000: Variable 'event_scheduler' can't be set to the value of '2' +"DISABLE the scheduler. Testing that it does not work when the variable is 0" +set global event_scheduler=0; +select definer, name, db from mysql.event; +definer name db +select get_lock("test_lock1", 20); +get_lock("test_lock1", 20) +1 +create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20); +"Should return 1 row" +select definer, name, db from mysql.event; +definer name db +root@localhost закачка events_test +"Should be only 1 process" +show processlist; +Id User Host db Command Time State Info +# root localhost events_test Query # NULL show processlist +select release_lock("test_lock1"); +release_lock("test_lock1") +1 +drop event закачка; +"Should have 0 events" +select count(*) from mysql.event; +count(*) +0 +"ENABLE the scheduler and get a lock" +set global event_scheduler=1; +select get_lock("test_lock2", 20); +get_lock("test_lock2", 20) +1 +"Create an event which tries to acquire a mutex. The event locks on the mutex" +create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20); +"Let some time pass to the event starts" +"Should have only 3 processes: the scheduler, our conn and the locked event" +show processlist; +Id User Host db Command Time State Info +# root localhost events_test Query # NULL show processlist +# event_scheduler NULL Connect # Sleeping NULL +# root events_test Connect # User lock select get_lock("test_lock2", 20) +"Release the mutex, the event worker should finish." +select release_lock("test_lock2"); +release_lock("test_lock2") +1 +drop event закачка; +set global event_scheduler=1; +select get_lock("test_lock2_1", 20); +get_lock("test_lock2_1", 20) +1 +create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20); +"Should see 2 processes, one locked on get_lock(" +"Shutting down the scheduler, it should wait for the running event" +set global event_scheduler=0; +"Should have only 3 processes: the scheduler, our conn and the locked event" +show processlist; +Id User Host db Command Time State Info +# root localhost events_test Query # NULL show processlist +# event_scheduler NULL Connect # Sleeping NULL +# root events_test Connect # User lock select get_lock("test_lock2_1", 20) +"Release the lock so the child process should finish. Hence the scheduler also" +select release_lock("test_lock2_1"); +release_lock("test_lock2_1") +1 +"Should have only our process now:" +show processlist; +Id User Host db Command Time State Info +# root localhost events_test Query # NULL show processlist +drop event закачка21; drop database events_test; diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index be24d490393..14acdb44038 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -17,12 +17,12 @@ drop event event2; create event e_43 on schedule every 1 second do set @a = 5; set global event_scheduler = 1; -select sleep(2); +--sleep 2 alter event e_43 do alter event e_43 do set @a = 4; -select sleep(3); +--sleep 2 select db, name, body, status, interval_field, interval_value from mysql.event; drop event e_43; -select sleep(1); +--sleep 1 set global event_scheduler = 0; create table t_event3 (a int, b float); @@ -107,8 +107,8 @@ drop event one_event; ##INFORMATION_SCHEMA.EVENTS test end # - - +--echo "Sleep a bit so the server closes the second connection" +--sleep 2 create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; @@ -129,23 +129,38 @@ set event_scheduler=0; --error 1231 set global event_scheduler=2; -#set global event_scheduler=0; -#select count(*) from mysql.event; -#select get_lock("test_lock1", 20); -#create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20); -#select count(*) from mysql.event; -##show processlist; -#select release_lock("test_lock1"); -#drop event закачка; -#select count(*) from mysql.event; +--echo "DISABLE the scheduler. Testing that it does not work when the variable is 0" +set global event_scheduler=0; +select definer, name, db from mysql.event; +select get_lock("test_lock1", 20); +create event закачка on schedule every 10 hour do select get_lock("test_lock1", 20); +--echo "Should return 1 row" +select definer, name, db from mysql.event; + +--echo "Should be only 1 process" +--replace_column 1 # 6 # +show processlist; +select release_lock("test_lock1"); +drop event закачка; +--echo "Should have 0 events" +select count(*) from mysql.event; + # -#set global event_scheduler=1; -#select get_lock("test_lock2", 20); -#create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20); -#select sleep(2); -#show processlist; -#select release_lock("test_lock2"); -#drop event закачка; +# +# +--echo "ENABLE the scheduler and get a lock" +set global event_scheduler=1; +select get_lock("test_lock2", 20); +--echo "Create an event which tries to acquire a mutex. The event locks on the mutex" +create event закачка on schedule every 10 hour do select get_lock("test_lock2", 20); +--echo "Let some time pass to the event starts" +--sleep 2 +--echo "Should have only 3 processes: the scheduler, our conn and the locked event" +--replace_column 1 # 6 # +show processlist; +--echo "Release the mutex, the event worker should finish." +select release_lock("test_lock2"); +drop event закачка; ## ## 1. get a lock @@ -155,26 +170,33 @@ set global event_scheduler=2; ## 5. kill the scheduler, it will wait for the child to stop ## 6. both processes should be there on show processlist ## 7. release the lock and sleep, both scheduler and child should end -#set global event_scheduler=1; -#select get_lock("test_lock2_1", 20); -#create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20); -#select sleep(2); -##show processlist; -#set global event_scheduler=0; -#select sleep(2); -##show processlist; -#select release_lock("test_lock2_1"); -#select sleep(2); -##show processlist; -#drop event закачка21; - -#set global event_scheduler=1; -#select get_lock("test_lock3", 20); -#create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20); -#select sleep(2); +set global event_scheduler=1; +select get_lock("test_lock2_1", 20); +create event закачка21 on schedule every 10 hour do select get_lock("test_lock2_1", 20); +--sleep 1 +--echo "Should see 2 processes, one locked on get_lock(" #show processlist; -#drop event закачка; -#select release_lock("test_lock3"); +--echo "Shutting down the scheduler, it should wait for the running event" +set global event_scheduler=0; +--sleep 1 +--echo "Should have only 3 processes: the scheduler, our conn and the locked event" +--replace_column 1 # 6 # +show processlist; +--echo "Release the lock so the child process should finish. Hence the scheduler also" +select release_lock("test_lock2_1"); +--sleep 1 +--echo "Should have only our process now:" +--replace_column 1 # 6 # +show processlist; +drop event закачка21; + +##set global event_scheduler=1; +##select get_lock("test_lock3", 20); +##create event закачка on schedule every 10 hour do select get_lock("test_lock3", 20); +##select sleep(2); +##show processlist; +##drop event закачка; +##select release_lock("test_lock3"); # # test with very often occuring event @@ -182,14 +204,15 @@ set global event_scheduler=2; ##select get_lock("test_lock4", 20); ##create event закачка4 on schedule every 1 second do select get_lock("test_lock4", 20); ##select sleep(3); +##--replace_column 1 # 6 # ##show processlist; ##drop event закачка4; ##select release_lock("test_lock4"); -#set global event_scheduler=0; -#select sleep(2); +##set global event_scheduler=0; +##select sleep(2); +##--replace_column 1 # 6 # ##show processlist; -##the following locks for some reason and is a bug, commented for now ##select count(*) from mysql.event; drop database events_test; diff --git a/sql/event.cc b/sql/event.cc index abca622835a..a7c6d48b988 100644 --- a/sql/event.cc +++ b/sql/event.cc @@ -704,11 +704,17 @@ done: } +/* + 0 - OK can drop from outside + 1 - Scheduled from dropping, don't drop from outside +*/ + static int evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock, bool is_drop) { uint i; + int ret= 0; DBUG_ENTER("evex_remove_from_cache"); /* @@ -738,7 +744,8 @@ evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock, DBUG_PRINT("evex_remove_from_cache", ("running.defer mem free. is_drop=%d", is_drop)); et->flags|= EVENT_EXEC_NO_MORE; - et->dropped= is_drop; + if ((et->dropped= is_drop)) + ret= 1; } DBUG_PRINT("evex_remove_from_cache", ("delete from queue")); evex_queue_delete_element(&EVEX_EQ_NAME, i); @@ -751,7 +758,7 @@ done: if (use_lock) VOID(pthread_mutex_unlock(&LOCK_event_arrays)); - DBUG_RETURN(0); + DBUG_RETURN(ret); } @@ -866,21 +873,25 @@ done: Drops an event SYNOPSIS - evex_drop_event() + db_drop_event() thd THD et event's name drop_if_exists if set and the event not existing => warning onto the stack + rows_affected affected number of rows is returned heres */ -int -evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists, - uint *rows_affected) +int db_drop_event(THD *thd, event_timed *et, bool drop_if_exists, + uint *rows_affected) { TABLE *table; - int ret= EVEX_OPEN_TABLE_FAILED; - DBUG_ENTER("evex_drop_event"); + Open_tables_state backup; + uint ret; + + DBUG_ENTER("db_drop_event"); + ret= EVEX_OPEN_TABLE_FAILED; + thd->reset_n_backup_open_tables_state(&backup); if (evex_open_event_table(thd, TL_WRITE, &table)) { my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); @@ -908,10 +919,6 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists, goto done; } - VOID(pthread_mutex_lock(&LOCK_evex_running)); - if (evex_is_running) - ret= evex_remove_from_cache(&et->dbname, &et->name, true, true); - VOID(pthread_mutex_unlock(&LOCK_evex_running)); done: /* @@ -919,6 +926,44 @@ done: we have to close our thread tables. */ close_thread_tables(thd); + thd->restore_backup_open_tables_state(&backup); + DBUG_RETURN(ret); +} + + +/* + Drops an event + + SYNOPSIS + evex_drop_event() + thd THD + et event's name + drop_if_exists if set and the event not existing => warning onto the stack + rows_affected affected number of rows is returned heres + +*/ + +int +evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists, + uint *rows_affected) +{ + TABLE *table; + int ret= 0; + + DBUG_ENTER("evex_drop_event"); + + + VOID(pthread_mutex_lock(&LOCK_evex_running)); + if (evex_is_running) + ret= evex_remove_from_cache(&et->dbname, &et->name, true, true); + VOID(pthread_mutex_unlock(&LOCK_evex_running)); + + if (ret == 1) + ret= 0; + else if (ret == 0) + ret= db_drop_event(thd, et, drop_if_exists, rows_affected); + else + my_error(ER_UNKNOWN_ERROR, MYF(0)); DBUG_RETURN(ret); } diff --git a/sql/event_priv.h b/sql/event_priv.h index 7d1cdbcd264..b0ba205d806 100644 --- a/sql/event_priv.h +++ b/sql/event_priv.h @@ -40,6 +40,9 @@ evex_db_find_event_aux(THD *thd, const LEX_STRING dbname, int event_timed_compare_q(void *vptr, byte* a, byte *b); +int db_drop_event(THD *thd, event_timed *et, bool drop_if_exists, + uint *rows_affected); + #define EXEC_QUEUE_QUEUE_NAME executing_queue #define EXEC_QUEUE_DARR_NAME evex_executing_queue diff --git a/sql/event_timed.cc b/sql/event_timed.cc index 28d21089b74..e585f6252ca 100644 --- a/sql/event_timed.cc +++ b/sql/event_timed.cc @@ -877,20 +877,10 @@ int event_timed::drop(THD *thd) { TABLE *table; - int ret= 0; + uint tmp= 0; DBUG_ENTER("event_timed::drop"); - if (evex_open_event_table(thd, TL_WRITE, &table)) - DBUG_RETURN(-1); - - if (evex_db_find_event_aux(thd, dbname, name, definer, table)) - DBUG_RETURN(-2); - - if ((ret= table->file->ha_delete_row(table->record[0]))) - DBUG_RETURN(ret); - - close_thread_tables(thd); - DBUG_RETURN(0); + DBUG_RETURN(db_drop_event(thd, this, false, &tmp)); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 279a02fa1d1..e9fb004b316 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3743,6 +3743,8 @@ end_with_restore_list: res= evex_drop_event(thd, lex->et, lex->drop_if_exists, &rows_affected); default:; } + DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d", + res, rows_affected)); if (!res) send_ok(thd, rows_affected); |